Python装饰器原理解析与元数据保护

夏知夏
夏知夏
发布时间:2026-10-16| 14人浏览过
原创

本文深入解析Python装饰器的底层原理,说明其本质为高阶函数的嵌套调用。重点探讨使用装饰器后函数元数据(如名称、文档)丢失的问题,并演示如何利用functools模块中的@wraps装饰器保留原始函数信息,确保代码的可维护性与规范性。

Python装饰器用法

Python的装饰器功能强大,能够处理多种场景。

然而对于初学者而言,其语法和机制可能显得不够直观。

实际上,装饰器本质上只是一个普通的函数。

import time
def log(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print("The func '{}' used {}s.".format(func.__name__, end-start))
        return result
    return warpper

当我们以如下方式调用装饰器时:

@log
def fucok(name):
    """Fucok someone"""
    print("Fucok", name)

它实际上等价于执行了 fucok = log(fucok) 这一行代码。

这意味着,表面上我们调用的是 fucok("myself"),但实际执行的是 log(fucok)("myself")。这是因为在Python中,函数也是对象。

同理,如果我们定义一个带参数的装饰器 logging,其实际执行逻辑为:

func = logging(arguments)(func)

即在不带参数装饰器的基础上,再增加一层函数定义即可。

import time
def logging(arguments):
    def log(func):
        def warpper(*args, **kwargs):
            start = time.time()
            result = func(*args, **kwargs)
            end = time.time()
            print("The func '{}' used {}s.".format(func.__name__, end-start))
            return result
        return warpper
    # do something
    return log

但是,应用装饰器后,原函数的元数据会被覆盖,例如函数名称、文档字符串等。

以上述代码为例:

print(fucok.__name__)
print(fucok.__doc__)

你会发现,函数的元信息全部丢失!fucok 的名称变成了 wrapper,其文档字符串也变为 None。

解决方法很简单:在定义装饰器时,使用 wraps 装饰器包裹接收原函数的那一层。

来自 functools 模块的 wraps 装饰器可以将原函数的元数据复制到被包装的函数上。

修改后的装饰器如下(仅增加了一行代码):

import time
from functools import wraps
def log(func):
    @wraps(func)
    def warpper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print("The func '{}' used {}s.".format(func.__name__, end-start))
        return result
    return warpper

再次运行:

print(fucok.__name__)
print(fucok.__doc__)

此时可以看到,函数的元信息已恢复正常。

在定义装饰器时添加 @wraps 是一个良好的编程习惯。

一个较为实用的装饰器示例见本专题的另一篇文章:函数参数类型检查。

总结

以上为个人经验总结,希望能为大家提供参考,也希望大家多多支持本站。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。