1. Write in front
Before we introduce Python decorator, we first introduce a concept of python, object. In Python, everything is an object. Common Python objects include integer objects, floating-point objects, string objects, list objects, tuple objects, dictionary objects, etc. One of the more special objects is the function object.
num1 = 1 defines an integer object, which num1 references
str1 = "aaa" ා defines a string object, which is referenced by str1
list1 = [1,2,3] ා defines a list object, which is referenced by list1
Def my func() defines a function object
print "hello world"
Func1 = my func func1 refers to this function object
Take a normal function for example.
def my_func(name):
return "name is {}".format(name)
Here we define a function called my_func, pass in a string object as the parameter of the function, and then return another string object. As mentioned above, in python, everything is an object. What if we passed in a function object as an argument and then returned another function? This is the decorator.
2. Basic decorator
Next to the question above, let's write a function like this.
def add(a, b): defines a function object
return a + b
Myadd = add ා myadd refers to this function object
def decorator1(func): defines a function object, decorator1, and the required parameter is also a function object
def log(*args, **kwargs): ා a new function object log is defined in the function
return func(*args, **kwargs)
return log returns the log function object
mydecorator = decorator1(myadd) ා call function decorator1, pass in myadd as a parameter, and assign the returned object to mydecorator at the same time. It can be seen that log function is returned here,
#In other words, mydecorator points to the log function
print mydecorator(1, 2) - call the mydecorator function, that is, call the internal log function
Take a look at the execution result of this code
C:\Python>python mydecorator1.py
3
We can see that its execution result is 3. You may ask if you have written so much, is not it the sum of two numbers? Isn't that the add function above? The above code is just for your understanding. What if we add some operations to the internal log function? For example, printing logs.
def add(a, b):
return a + b
myadd = add
def minus(a, b):
return a - b
myminus = minus
def decorator1(func):
def log(*args, **kwargs):
# do some things here, for example, add some log
print "function {} was called".format(func.__name__)
return func(*args, **kwargs)
return log
mydecorator1 = decorator1(myadd)
mydecorator2 = decorator1(myminus)
print mydecorator1(1, 2)
print mydecorator2(3, 4)
Let's take a look at the execution result of this code
C:\Python>python mydecorator1.py
function add was called
3
function minus was called
-1
We only need to modify the internal log function to realize the function of extended function, and this function can be applied to multiple functions. This is the biggest significance of decorators. Here I take adding logs as an example. In practical work, for example, I write a decorator to determine whether the login operation is needed.
3. python decorator syntax sugar
In the actual work of python, the @ symbol is usually used to call the decorator, which is called Python syntax sugar.
def decorator1(func):
def log(*args, **kwargs):
# do some things here, for example, add some log
print "function {} was called".format(func.__name__)
return func(*args, **kwargs)
return log
@decorator1
def add(a, b): at this time, add = decorator1(add), and the add function is decorated
return a + b
@decorator1
def minus(a, b): ා now minus = decorator1(minus), the minus function is decorated
return a - b
print add(1,2) executes the decorated add function instead of the original add function
print minus(3,4) executes decorated minus functions instead of the original minus functions
4. Advanced decorator
The above introduces the basic decorators, and the following introduces some advanced usage of decorators.
4.1 decorator with parameters
In the above example, we can see that the decorated function add, minus has parameters, but decorator 1 itself can not have other parameters except func. Is there any way to make the decorator with other parameters? Such as string parameters. The answer is yes, just encapsulate a function at the outermost layer.
def decorator2(mystring):
print mystring
def decorator1(func):
def log(*args, **kwargs):
# do some things here, for example, add some log
print "function {} was called".format(func.__name__)
return func(*args, **kwargs)
return log
return decorator1
@decorator2("Used decorator here")
def add(a, b):
return a + b
@decorator2("Used decorator here")
def minus(a, b):
return a - b
print add(1,2)
print minus(3,4)
Let's see the execution result of this code
C:\Python>python mydecorator1.py
Used decorator here
Used decorator here
function add was called
3
function minus was called
-1
4.2 multiple decoration
Up to now, we only use one decorator. What if we apply multiple decorators?
from functools import wraps
def decorator1(func):
@wraps(func)
def log(*args, **kwargs):
# do some things here, for example, add some log
print "function {} was called in decorator1".format(func.__name__)
return func(*args, **kwargs)
return log
def decorator2(func):
@wraps(func)
def another_log(*args, **kwargs):
# do some things here, for example, add some log
print "function {} was called in decorator2".format(func.__name__)
return func(*args, **kwargs)
return another_log
@decorator1
@decorator2
def add(a, b):
return a + b
add(1, 2)
@decorator2
@decorator1
def minus(a, b):
return a - b
minus(3, 4)
Let's see the execution result of this code
C:\Python>python mydecorator1.py
function add was called in decorator1
function add was called in decorator2
function minus was called in decorator2
function minus was called in decorator1
5. Decorator summary
- A decorator is a function that receives a function object and returns a new function object.
- The decorator can extend the code function without modifying the decorated function, without rewriting or refactoring the code.
- The decorator can be used to add extended logs to judge whether a user needs to log in for an operation, whether it is legal, etc.
- The decorator itself can also carry the required additional parameters.
- For multiple decorations, the order of decoration is the calling order of decorators.