Introduction to decorators:
Decorator (decorator) is an advanced Python syntax. Decorators can process a function, method or class. In Python, we have many ways to process functions and classes. For example, in Python closures, we see function objects as the return result of a certain function. Compared with other methods, the decorator syntax is simple and the code is highly readable. Therefore, decorators are widely used in Python projects.
The decorator first appeared in Python 2.5. It was originally used to process callable objects such as functions and methods (callable objects, such objects are defined with a __call__ method). In Python 2.6 and later Python versions, decorators are further used to process classes.
Decorators are mainly used to wrap functions for some commonly used functions, such as: log printing, function timing, and identity authentication. We can use decorators to achieve this, which can reduce the complexity of the entire program and reduce the amount of code in the program.
It is actually a function. The difference is that it takes a function as a parameter and then returns an alternative version of the function.
Let’s look at a simple example:
def add_number(func): def adder(arg): return func(arg)+100 return adder def f(x): return x f=add_number(f) print f(20)
add_number is a decorator function that accepts a function (f) as a parameter and then returns another The function (adder) is assigned to the original function, so that the original function can implement the addition function without adding additional code.
This is the original implementation of the decorator.
But, this method is still a bit inconvenient. After all, we still go around in a circle and use f=add_number(f) to reassign the original function.
In fact, the following methods can be used to simplify the reference to decorators in Python.
def add_number(func): def adder(arg): return func(arg)+100 return adder @add_number def f(x): return x print f(20)
It only requires a simple @add_numbe call. Isn’t it convenient? It’s much simpler and basically does not invade the original code.
Well, everyone noticed that as a decorator, there are only two parameters accepted each time: functions and function parameters, but the writing format is basically the same. Is there any way to simplify this kind of writing?
Yes, Python provides a decorator package, which can greatly simplify the writing of decorators.
So, the third implementation method is:
from decorator import decorator @decorator def wrapper(func,arg): return func(arg)+100 @wrapper def f(x): return x print f(20)
Oh, it is indeed simpler~
The above example is accepted All have one parameter. In fact, the function itself can accept variable parameters.
For example:
@decorator def wrapper(f,arg1,*args,**kwargs): print "I am just a wrapper~" return f(arg1,*args,**kwargs) @wrapper def f(arg1,*args,**kwargs): print arg1 for eacheArg in args: print 'non-keyword arg:',eacheArg for eachKw in kwargs.keys(): print 'keyword arg: %s:%d' % (eachKw,kwargs[eachKw]) args=('Joy','Steve') kwargs={"age":20} f('China',*args,**kwargs)
The output result is:
I am just a wrapper~ China non-keyword arg: Joy non-keyword arg: Steve keyword arg: age:20
About the difference between *args and **kwargs , both can be used to represent variable-length arguments. It's just that the former is represented by Yuanzu and has no key value, while the latter is a dictionary with key value. Both can be used in the same function, however, *args must appear before **kwargs.
For example:
def test_var_args_call(arg1, arg2, arg3): print "arg1:", arg1 print "arg2:", arg2 print "arg3:", arg3 args=(1,2,3) kwargs ={"arg1":"1","arg3": 3, "arg2": "2"} test_var_args_call(*args) print '-----------------' test_var_args_call(**kwargs)
The implementation effect of both is the same.
The last example is to decorate a function by displaying the execution time of the function
import time def log(func): def wrapper(*args, **kw): print '[%s] %s() was called...' % (time.ctime(),func.__name__) return func(*args, **kw) return wrapper @log def foo(): pass for i in range(4): foo() time.sleep(1)
The output result is as follows:
[Wed Jul 27 09:17:23 2016] foo() was called... [Wed Jul 27 09:17:24 2016] foo() was called... [Wed Jul 27 09:17:25 2016] foo() was called... [Wed Jul 27 09:17:26 2016] foo() was called...
The above is the in-depth understanding of Python decorators introduced by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. I would also like to thank you all for your support of the PHP Chinese website!
For more in-depth understanding of Python decorator-related articles, please pay attention to the PHP Chinese website!