Python 3.6.8
Before you understand the decorator , we need to understand what a closure function is.
Let’s simply write a demo
and explain what a closure function is.
def exterFunc(x): def innerFunc(y): return x * y return innerFunc def main() -> None: f = exterFunc(6) result = f(5) print(result) if __name__ == '__main__': main()
As you can see, as shown in the above code, the so-called closure function refers to: A closure function refers to a function defined within a function. The internal function can access external variables. In the external function , return the internal function as the return value.
As you can see in the above example, we defined the function exterFunc
, which will receive a formal parameter x
, in exterFunc
innerFunc
is defined in the function, which also receives a formal parameter y
. In the innerFunc
function, x * y
is returned. Yes, the internal function can access the variables passed in by the external function, and finally returns exterFunc
as the return value. This is the closure function.
The decorator is a very special function that can receive a function as a formal parameter and return a new function. In our previous article, we introduced the generator At that time, do you still remember that we used the memory_profiler
library to print the memory operation status of the function? This is the decorator used.
We can write the simplest example to explain the python
decorator, that is:
def foo(func): def wrapper(): print("装饰器开始运行了") func() print("装饰器结束运行了") return wrapper @foo def sayHello(): print("hello pdudo in juejin") def main() -> None: sayHello() if __name__ == '__main__': main()
In the above code, we A decorator foo
is defined, foo
needs to pass in a function, foo
has a function wrapper
inside. We call a function wrapped in such a function a closure function, and closure functions will be introduced later. Closer to home, in the wrapper
function, we can execute the preceding and following statements when running the func
function.
When you need to call the decorator, you only need to @
add the function name.
To explain this problem, we can look at what problems the decorator solves:
Solution code Repetitiveness. For those who often need to implement similar functions, the function can be extracted and called as a decorator to avoid code duplication.
Enhance code readability. You can use decorators to add code before and after functions without modifying the original code, such as handling exceptions, recording logs, etc. You can use decorators Separate additional functions from the main functions of the function to increase code readability.
Having said so much, let’s enumerate the simplest example and use the decorator to print the running time of the function.
import time def getExecTimers(func): def wrapper(): startTimes = time.time() func() endTimes = time.time() print("函数运行时间: " , endTimes - startTimes ,"s") return wrapper @getExecTimers def testFunc(): print("开始执行函数") time.sleep(5) print("函数执行结束") def main() -> None: testFunc() if __name__ == '__main__': main()
This decorator will record the running time of the function. As you can see, we added an additional function to this function, but did not modify the original function.
The above case should be able to prove why you need to use decorators.
Above we discussed the simplest way to write a decorator, and wrote a small function, which is to print the running time of the function. Next, we have to look at other ways to write decorators.
Do you remember that when we called the decorator above, we used the @
decorator name? In fact, this is syntax sugar for python
. If you don’t use syntax sugar, it should be used like this:
def foo(func): def wrapper(): print("装饰器开始运行了") func() print("装饰器结束运行了") return wrapper def sayHello(): print("hello pdudo in juejin") def main() -> None: f1 = sayHello f2 = foo(f1) f2() if __name__ == '__main__': main()
The complete writing method should be as shown in the following code. This is a complete closure. Package calling logic.
f1 = sayHello f2 = foo(f1) f2()
Adding the @
decorator name before the function is a kind of syntax sugar for python
Here is a foreshadowing. In python
, there are two special variables, namely *args
and **kwargs
, both Used to handle indefinite parameters, the respective meanings are:
*args
: The parameters will be packed into tuples
**kwargs
: The packed dictionary will be passed to the function
def foo(func): def wrapper(*args,**kwargs): print("装饰器开始运行了") print("装饰器捕获到的参数: " ,args,**kwargs) func(*args,**kwargs) print("装饰器结束运行了") return wrapper @foo def sayHello(a,b,c,dicts): print("传入的参数: " , a,b,c) print("传入的参数: " , dicts) def main() -> None: sayHello(1,2,3,{"name":"juejin"}) if __name__ == '__main__': main()
In the decorator, if we want to pass parameters to the function, it is necessary The parameters are passed to the decorator first, and then passed after being received in the decorator, so the code will be like this:
def foo(func): def wrapper(*args,**kwargs): print("装饰器开始运行了") print("装饰器捕获到的参数: " ,args,**kwargs) func(*args,**kwargs) print("装饰器结束运行了")
First of all, when we make the transfer call, wrapper
You should call the formal parameter to receive it, and then pass it to the function func
after receiving it.
The above is the detailed content of What are decorators in Python and how to use them. For more information, please follow other related articles on the PHP Chinese website!