Python 的装饰器(Decorator)就是出现在函数声明上方以 @
开头的语句,如下所示:
@log
def now():
print('2024-08-07')
这种语句可以拓展函数的功能,就像“装饰”了原本的函数一样,所以被称为装饰器。
而实际上它是一个语法糖,当我们调用 now()
的时候,实际上是调用了:
# now()
log(now)()
所以总的来说,实际调用的,其实是以 now
为参数(函数式编程)构造出的一个新函数,而非 now
了,更具体一些, log
可以实现成这个样子:
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
这是一种Python Closure的手法, wrapper
捕获了外部变量 func
,实际调用的是 wrapper
,而 wrapper
的效果是先打印一句 call funcname
,然后再调用 now
。此时调用 now()
的效果如下:
call now():
2024-08-07
更进一步,装饰器是可以有参数的,比如这种:
@log('execute')
def now():
print('2024-6-1')
这种语法糖的本质是:
# now()
log('execute')(now)()
因此,此时 log
会在外面多一层,用于接收装饰器参数:
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
闭包分别捕获了 text
和 func
。