Python中functools.wraps装饰器具体能解决哪些问题?
看到 fluent python 第 7 章例 7-15 中写道:
最开始实现的装饰器有几个缺点:不支持关键字参数,而且遮盖了被装饰函数的 name 和 doc 属性。
之后用 functools.wraps 解决。函数自身的属性好理解,但是为什么新版能够正确处理关键字参数呢?
附上前后两个装饰器代码 https://notepad.pw/code/c2cetz9um
Python中functools.wraps装饰器具体能解决哪些问题?
因为他本身的实现类似于
def wraps(func):
def _warps(_func):
_func.name=func.name
_func.doc=func.doc
return _func
return _warps
functools.wraps 主要解决装饰器导致的元信息丢失问题。
比如你写个装饰器:
def my_decorator(func):
def wrapper(*args, **kwargs):
"""包装函数"""
return func(*args, **kwargs)
return wrapper
@my_decorator
def example():
"""这是原函数"""
pass
print(example.__name__) # 输出 'wrapper',而不是 'example'
print(example.__doc__) # 输出 '包装函数',而不是 '这是原函数'
这里被装饰后,函数的 __name__、__doc__ 等属性变成了内层包装函数的,破坏了原始信息。
用 functools.wraps 修复:
from functools import wraps
def my_decorator(func):
@wraps(func) # 关键在这里
def wrapper(*args, **kwargs):
"""包装函数"""
return func(*args, **kwargs)
return wrapper
@my_decorator
def example():
"""这是原函数"""
pass
print(example.__name__) # 输出 'example'
print(example.__doc__) # 输出 '这是原函数'
wraps 本质是把原函数的 __module__、__name__、__doc__ 等属性复制到装饰器返回的函数上,让装饰器对使用者更透明。
一句话总结:用它保持被装饰函数的元信息。
重新排版一下
def wraps(func):
----def _warps(_func):
--------_func.name=func.name
--------_func.doc=func.doc
--------return _func
----return _warps
至于“装饰器不支持关键词参数”,好奇具体是怎么个不支持法,请说明具体的不支持的写法
我就是看原文是直接这么写的才问的。
楼主试试用 Pycharm 去 Ctrl + B 吧 😀
"Sadly most decorators are broken because the web is full of bad advice."
https://hynek.me/articles/decorators/

