python中functools.wraps使用原理

本文详细解析了Python中装饰器的原理及其如何通过functools.update_wrapper保持被装饰函数的元数据。通过实例展示了如何使用@functools.wraps简化装饰器的编写过程,确保装饰后的函数仍能正确反映其原始属性。
摘要由CSDN通过智能技术生成
functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
  • 此函数的作用是更新包装器函数看起来像被它包装起来的函数。它的可选的元组参数列举了原函数声明的哪些属性可直接与包装器函数的属性相匹配,包装器哪些属性需更新以符合原函数的属性。这些参数的默认值是模块级的常量WRAPPER_ASSIGNMENTS(包装器函数声明的__module__ ,__ name __, __ qualname __, __ annotations __ 和 __ doc __ 文档字符串)和 WRAPPER_UPDATES(更新包装器函数的 __ dict __ ,等实例的字典信息)
  • 为了方便获的原函数内部的信息和其它目的,这个函数将自动为包装器函数添加一个 __ wrapped __ 属性,以此为关联被包装的函数。
  • 这个函数的主要目的是用在装饰器函数里,装饰器函数装饰一个函数,并且返回的包装函数。如果这个包装函数没有更新,返回的函数的元数据将使用包装函数的定义,而不是原函数的定义,因为那些通常是没有多大用处的。
  • update_wrapper()可以与其它可调用函数一起使用,任可在assigned o或updated中声明的属性,如果在被包装的函数找不到,那么就会被忽略(也就是说这个函数不会把这些性属赋予包装器涵数)。如果包装器函数本身不含所有在updated中命名的属性,那么将报属性错误 AttributeError
@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
  • 当我们定义一个包装器函数时,可以用这个便捷函数调用update_wrapper() 函数作为函数的装饰器。
from functools import wraps
def my_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        print('Calling decorated function')
        return f(*args, **kwds)
    return wrapper

@my_decorator
def example():
    """Docstring"""
    print('Called example function')

如上所述,@wraps(f)将调用update_wrapper() 函数作为wrapper函数的装饰器,使闭包更新并保留原函数的属性。

>>> example()
Calling decorated function
Called example function
>>> example.__name__
'example'
>>> example.__doc__
'Docstring'

感悟:原函数被装饰后,调用原函数其实调用的是一个闭包,也就是装饰器返回的包装器函数return wrapper。可以说原函数经过装饰后变成了一个新的函数,只是函数名相同的函数而已。

官网链接:https://docs.python.org/3/library/functools.html?highlight=functools wraps#functools.update_wrapper

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值