看代码的时候经常会看到函数定义之前有一个"@xxx",如下:
@lol
def pop():
...
这就是本文要介绍的装饰器(decorator)了。
装饰器可以使代码更简洁,更具有层次性和可读性。它的作用是:给函数增加额外的功能。这样一来,我们在编写python函数时,可以尽量把函数功能拆分,然后用最常用的功能作为装饰器就可以极大程度压缩代码。
我们来抛砖引玉:
def deco(func):
print('hehe')
return func
def target():
print('xixi')
deco(target())
输出为:
$ python decorator.py
xixi
hehe
通过函数嵌套调用的方法,可以实现给函数增加额外功能(本来只能打印“hehe”,现在还能打印“xixi”),但显得十分臃肿。我们用装饰器改进一下:
def deco(func):
print('hehe')
return func
@deco
def target():
print('xixi')
target()
输出为:
$ python decorator.py
hehe
xixi
比较上面两种情况下的输出我们可以发现:hehe与xixi的顺序是反的。在装饰器里,只有return func的时候才执行被装饰的函数。然后呢,用装饰器完全不影响被装饰函数传参:
def deco(func):
print('3 + 4 = ', end='')
return func
@deco
def target(a, b):
res = a + b
print(res)
target(3,4)
输出为:
$ python decorator.py
3 + 4 = 7
做个稍微复杂功能,可以传递参数的装饰器:
def deco(a, b):
ab = a*b
print('*'*ab)
def wrapper(func):
return func
return wrapper
@deco(2,5)
def target(a, b):
res = a+b
print(res)
target(3,4)
可以对装饰器进行传参,这样只需要将基本功能的装饰器包含进去就行了。输出为:
$ python decorator.py
**********
7
如果希望装饰器不光增加前奏功能,还能增加后面的功能,可以使用wrapper进行 :
def deco(func):
def deco_core(a,b):
ab = a*b
print('start:')
func(a, b)
print('*'*ab)
return deco_core
@deco
def target(a, b):
res = a+b
print(res)
target(3,4)
输出为:
$ python decorator.py
start:
7
************
实例应用--函数运行时间计算
我设计一个可以计算函数运行的函数当作解释器,代码如下:
from time import time
def time_costing(func):
def core():
start = time()
func()
print('time costing:', time() - start)
return core
@time_costing
def run():
res = 0
for i in range(10000):
for j in range(10000):
res += 1
res -= 1
if __name__ == '__main__':
run()
总结
python装饰器可以增加函数的功能。可以使用wrapper,适当给函数增加前奏或者末尾功能。