写点什么

装饰器 @wraps 到底是个啥

作者:LLLibra146
  • 2024-11-05
    北京
  • 本文字数:1457 字

    阅读完需:约 5 分钟

引言

在前面的文章中,介绍了 Python 装饰器的各种使用方式和概念,而在使用装饰器时,@wraps 是一个非常重要的工具,它帮助我们保持被装饰函数的元数据。本文将深入探讨 @wraps 的作用及其重要性。


@wraps 的作用

@wraps 的定义

@wrapsfunctools 模块中的一个装饰器,它用于装饰另一个装饰器。它的主要功能是将被装饰函数的元数据(如函数名、文档字符串等)复制到装饰器内部的函数上。

什么是元数据?

元数据是关于数据的数据,可以简单理解为数据库的字段的解释。在 Python 编程中,元数据通常指的是描述函数、类或模块的属性,例如:


  • 函数名:函数的名称。

  • 文档字符串:描述函数功能的字符串,通常用于帮助文档。

  • 参数信息:函数接受的参数及其类型。

  • 返回值:函数返回的值的类型。


在 Python 中,元数据可以通过 __name____doc__ 等特殊属性访问。来看一个例子:


def doc():    """    demo func
:return: None """ print(1)

print(doc.__name__)print(doc.__doc__)
复制代码


运行结果为:


doc
demo func
:return: None
复制代码


可以看到, __name__ 输出了函数的名字,而 __doc__ 属性输出了函数的文档字符串。

为什么需要 @wraps

在使用装饰器时,通常会创建一个新的函数来包装原始函数,具体内容可以看上一篇文章。如果不使用 @wraps,这个新函数将会丢失原始函数的元数据。这可能会导致调试困难,因为错误信息和文档字符串将不再反映原始函数的内容。

@wraps 如何影响函数的元数据

使用 @wraps 后,被装饰函数的名称、文档字符串和其他属性将被复制到装饰器内部的函数上。在使用 help() 函数或查看函数的 __name____doc__ 属性时,能够看到原始函数的信息。

wraps 示例

下面是一个不使用 @wraps 的示例:


def my_decorator(func):    def wrapper(*args, **kwargs):        print("Before calling the function.")        result = func(*args, **kwargs)        print("After calling the function.")        return result
return wrapper

@my_decoratordef say_hello(name): """This function greets a person.""" print(f"Hello, {name}!")

say_hello("Alice")
print(say_hello.__name__)print(say_hello.__doc__)
复制代码


运行结果为:


Before calling the function.Hello, Alice!After calling the function.wrapperNone
复制代码


可以看到,运行结果的函数名属性和函数文档字符串属性都被修改了,原函数的数据都丢失了。为什么这里会丢失呢,装饰器的原理可以看我的上一篇文章。


下面是一个使用 @wraps 的示例:


from functools import wraps

def my_decorator(func): @wraps(func) def wrapper(*args, **kwargs): print("Before calling the function.") result = func(*args, **kwargs) print("After calling the function.") return result
return wrapper

@my_decoratordef say_hello(name): """This function greets a person.""" print(f"Hello, {name}!")

say_hello("Alice")
# 查看函数的元数据print(say_hello.__name__)print(say_hello.__doc__)
复制代码


运行结果为:


Before calling the function.Hello, Alice!After calling the function.say_helloThis function greets a person.
复制代码


可以看到,在添加了装饰器后,被装饰函数的各种属性都回来了,像没有被装饰过一样。

总结

@wraps 是 Python 装饰器中一个不可或缺的工具,它确保了被装饰函数的元数据可以不被覆盖。使用 @wraps 可以提高代码的可读性和可维护性,避免在调试时遇到困扰。

发布于: 刚刚阅读数: 3
用户头像

LLLibra146

关注

还未添加个人签名 2018-09-17 加入

还未添加个人简介

评论

发布
暂无评论
装饰器@wraps到底是个啥_Python_LLLibra146_InfoQ写作社区