Python中functools.wraps装饰器具体能解决哪些问题?

看到 fluent python 第 7 章例 7-15 中写道:

最开始实现的装饰器有几个缺点:不支持关键字参数,而且遮盖了被装饰函数的 namedoc 属性。

之后用 functools.wraps 解决。函数自身的属性好理解,但是为什么新版能够正确处理关键字参数呢?

附上前后两个装饰器代码 https://notepad.pw/code/c2cetz9um


Python中functools.wraps装饰器具体能解决哪些问题?

7 回复

因为他本身的实现类似于
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/

回到顶部