2分钟告诉你什么是python装饰器。
一、什么是装饰器
Python的装饰器的英文名叫Decorator
,这个和设计模式中的Decorator Pattern
是两种东西。
Python中的装饰器主要用于对已经有的模块做一些“修饰工作”。比如说,我们经常需要在函数调用前后自动打印日志,又不想要改变原有函数的模块,这个时候,我们便可以写一个打印log的装饰器。
二、Hello World
|
|
当运行代码,你会发现有如下输出:
有木有发现很神奇?
三、Decorator 的本质
对于Python的这个@注解语法糖来说,当你在用某个@decorator来修饰某个函数func时,如下所示:
相当于执行了语句:
其实就是把一个函数当参数传到另一个函数中,然后再把decorator这个函数的返回值赋值回了原来的func。
不信我们可以做如下验证:
还没有执行gfw就输出我们每个人的心声了有木有。
知道这点本质,当你看到有多个decorator:
相当于:
带参数的decorator:
相当于:
这意味着decorator(arg1, arg2)这个函数需要返回一个“真正的decorator”。
四、带参数的装饰器示例
假设我们可以编写一个带参数的装饰器:
@@log(‘SHUN_TAG’)实际上会执行如下语句:foo = log('SHUN_TAG')(foo)
然后最终会返回wrapper函数给foo,另外要记得wrapper.__name__ = func.__name__
,防止有些函数签名的代码回报错。
也可以用@functools.wraps(func)来代替上述写法:
其实也没有什么复杂的东西。
五、class式的 Decorator
最后再来看下decorator的class方式,还是看个示例:
用类的方式声明一个decorator。我们可以看到这个类中有两个成员:
- 一个是init(),这个方法是在我们给某个函数decorator时被调用,所以,需要有一个fn的参数,也就是被decorator的函数。
- 一个是call(),这个方法是在我们调用被decorator函数时被调用的。
上面输出可以看到整个程序的执行顺序。
六、总结
decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。
References: