current position:Home>Using class decorators in Python

Using class decorators in Python

2022-01-31 07:49:44 Nuggets translation program

This is my participation 11 The fourth of the yuegengwen challenge 6 God , Check out the activity details :2021 One last more challenge .

stay Python Examples and guidelines for using class decorators in

Decorator class

stay Python in , Decorators can be functions or classes . In both cases , Decorators can add functions to existing functions . When we decorate a function with a class , The function becomes an instance of the class . We can add functionality to functions by defining methods in decorator classes , All this can be achieved without modifying the source code .

This tutorial will demonstrate how to use classes to decorate our Python Functions in code . I'll show you two use cases , Namely : Decorate the function with a class that does not accept parameters , And class decorating functions that use acceptable parameters . If no parameters are passed , Our class will use the default value .

To help you understand , I have deliberately simplified the following example . Although we can use simpler alternatives to achieve similar results , But my main goal in this tutorial is to demonstrate how to use classes to decorate functions and extend their functionality .

This tutorial is also intended to show how to use decorator classes that accept parameters .

multiple_together function

multiple_together Function to get two integer values , Multiply them and return the result . Let's consider such a scenario , We want to add some extra functionality to this function without changing its source code . here , We want to square the returned value . We can do this using class decorators .

If you want to use a class as the decorator of a function , We have to write... Above the function definition @classNameclassName For class name ). By convention , Our class name will follow the hump nomenclature . In a class definition , We define two methods :__init__ Constructors and __call__ Method .

When we decorate a function with a class , This function automatically acts as __init__ The first argument to the constructor . We take this function as an attribute in our object . If we are going to multiply_together Print out , We will get one Power Class .

By defining __call__ Method , We can call... As before multply_together function . Here we can see that we will 2 multiply 2 And square the result .

__call__ Method has two parameters ( Because our original multiply_together There are two parameters in the function ). We will self._arg Set as decorated function ( The grammar is object.attribute). We call this function by passing two values , And save the return value to the variable retval in . Last , We are right. retval Square and return .

img

Power Class extends the original multiply_together Function functions .

The code for this example is as follows :

class Power(object):
	def __init__(self, arg):
		self._arg = arg

	def __call__(self, a, b):
		retval = self._arg(a, b)
		return retval ** 2


@Power
def multiply_together(a, b):
	return a * b


print(multiply_together)
print(multiply_together(2, 2))
 Copy code 

Expand multiply_together Function functions —— add to memory

To extend the example introduced in the previous section , We can do it for our Power Object to make room for storing the return value . We can be our object _memory Property to set an empty list , Each time the function is called, the value is added to the list and returned . Last , We can define a name as memory Methods , Used to return data stored in _memory Values in the list .

such , We further expanded multiply_together Function functions . The code of this example can be found in here find .

img

_memory Property is now a list of all the results . We just call Power Instance species memory Method to retrieve the results .

Class decorator that can accept parameters

To further increase the functionality of the example , It's great to let our class decorator accept parameters . In this way , We can customize it Power The index value of the class . Besides , If no parameters are passed to the class decorator , The default index value is used .

Pass parameters to the class decorator

When we pass parameters to the class decorator , This parameter will be __init__ Arguments to the constructor ( and Not a decorated function ). In the example , We'll take the integer value 3 Pass as parameter to Power Class constructor . This value is saved to the... Of the class _arg Properties of the . The decorated function will be used as __call__ The only argument to the method .

therefore , If passed to call The number of parameters of the method is equal to 1, That is, the decorated function is passed to the class as a parameter , be __call__ The first argument to the method will be the function . after , We can do it in __call__ Method to define an internal function , It takes two arguments ,a and b. If passed to __call__ The parameters of are 1, be __call__ Method returns wrapper function , We can call this function by passing two values , Finally, multiply the result by the integer originally passed to the class as a parameter ( Stored in properties _arg in )( See the example below ).

To give us __call__ Methods increase flexibility , We use *param_arg. This means that this parameter can accept a variable number of parameters .param_arg Store parameters in tuples , This allows us to easily check the number of parameters .

In order to better describe the process , I attached the corresponding example :

img

When no parameters are passed to the class decorator

Another case is that no parameters are passed to the class decorator . In this case , This function is passed in as the first function __init__ In the constructor . When we call the decorated function , We pass in two parameters , therefore __call__ The first condition in the method does not hold ,else Statement executed . here , The default value is 2 Is set to exponential . after , Stored in _arg The function in the property is called , The return value is stored in the variable retval in . Last ,retval Multiply by the default expo Value and returns .

You can here And the source code of the two examples found below .

Now both cases are satisfied —— We have a class decorator that can accept or not accept parameters . If no parameters are passed to the class decorator , Then it will use the default value .

img

#  Complete example , attach  docstring
class Power(object):
	def __init__(self, arg):
		self._arg = arg

	def __call__(self, *param_arg):
		"""If there are decorator arguments, __call__() is only called once as part of the decoration process. You can only give it a single argument, which is the function object. If there are no decorator arguments, the function to be decorated is passed to the constructor. """
		if len(param_arg) == 1:
			def wrapper(a, b):
				retval = param_arg[0](a, b)
				return retval ** self._arg
			return wrapper
		else:
			expo = 2
			retval = self._arg(param_arg[0], param_arg[1])
			return retval ** expo
        
        
# @Power(3)
@Power
def multiply_together(a, b):
	return a * b


print(multiply_together(2, 2))
 Copy code 

summary

The output of the above code can be realized in a simpler way , however , This article focuses on how to use class decorators , So I'm more focused on using examples that are easy to understand .

Functions can be decorated with classes to extend their functions . Besides , The class of decorating function can accept parameters , You can also use the default value without passing parameters . In this paper , We demonstrated these two use cases , Used to improve the function of the original function .

copyright notice
author[Nuggets translation program],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/01/202201310749411911.html

Random recommended