Python 装饰器和 functools 模块¶
@2016-04-20 新版功能: 创建
Python装饰器(decorator, PEP 318) 是很有用的一个语法特性。但在具体使用时,需要注意一些细节。例如, 被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变)。 因此,Python 的 functools 包中提供了一个叫 wraps 的装饰器来消除这样的副作用。
#!/usr/bin/python
# -*- coding=utf-8 -*-
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('Calling decorated function...')
return func(*args, **kwargs)
return wrapper
@my_decorator
def example():
"""Docstring of example"""
print('Called example function')
example()
print("example", example.__name__, example.__doc__)
运行结果:
Calling decorated function...
Called example function
('example', 'example', 'Docstring of example')
如果去掉 @wraps,则结果如下:
Calling decorated function...
Called example function
('example', 'wrapper', None)
其直接后果是导致所有被装饰的函数都具有相同的名字。在某些应用中函数名字是有 实际意义的。例如 Flask 应用里的路由规则。
functools 里还有更多的函数。例如 partial():
>>> from functools import partial
>>> int2 = partial(int, base=2)
>>> int2('11')
3
wraps 其实等价于 functools 里的 partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)。
update_wrappers() 则相当于把被封装函数的 module,name,doc 和 dict 复制到封装的函数中去。