Python装饰器分两种情况:
1.如果decorator本身不用传入参数的话,只是接受一个函数(当然也可以把接受的函数作为参数,为了区别,我们暂且将他们分开),并返回一个函数的话,当使用@log时即把目标函数接入;
2.如果decorator本身需要传入参数,那我们首先就需要在外层嵌套一个传入参数的接口,然后再接受函数并返回一个函数,内层则就是重复第一种情况,当时用@log('要传入的参数'),log('要传入的参数')就相当于第一种情况的log,也许这样说你还不是很能理解,我把廖大大的代码稍微做一点点改变,只改变下函数的名称:
1. 装饰器本身不用传入参数,只接收函数func
def decorator(func):
@functools.wraps(func)
def wrapper(*args, *kw):
print('call %s():' % func.name)
return func(args, **kw)
return wrapper
@decorator
def f():
pass
2. 装饰器本身需要传入参数,再接收函数func
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, *kw):
print('%s %s():' % (text, func.name))
return func(args, **kw)
return wrapper
return decorator
@log('execute')
def f():
pass
其中第二种情况@log('execute')就是传入了字符串参数的decorator,传入参数之后就完全等同于第一种情况的@decorator,log只是在第一种情况下作为实现传入字符串参数功能的外层,可以发现第二种情况的内层完全和第一种情况相同。线性的把第二种情况展开:首先log()传入字符串参数,然后返回decorator接受目标函数func,返回wrapper,最后wrapper输出内容并运行目标函数。明显传入字符串参数之后完全和第一种情况一致。
其他相关帮助理解资料:
探究functools模块wraps装饰器的用途 - 大道曙光
[译] 12步轻松搞定python装饰器