Python内部:装饰器

发布: (2026年2月21日 GMT+8 09:42)
4 分钟阅读
原文: Dev.to

Source: Dev.to

介绍

让我们拆解抽象层,从头开始构建装饰器,使用堆分配、闭包和时间复杂度作为指引。

如果你来自 C++ 或 Java 等静态、编译型背景,Python 装饰器可能会感觉像黑魔法。你在函数上方加上 @login_required,它立刻拥有了认证逻辑。再加上 @app.route("/"),它立刻变成了一个 Web 端点。

之所以感觉像魔法,是因为它隐藏了复杂性。但作为工程师,我们知道 魔法 只是我们尚未理解的代码。

在本文中,我们将揭开 Python 元编程的神秘面纱。我们不仅要学习 如何 使用装饰器,还要理解使其成为可能的内存机制,构建一个可投入生产的工具箱,并利用它们从根本上改变函数的算法复杂度。

第 1 部分:机制(不允许使用魔法)

在编写装饰器之前,我们需要了解原材料。在 Python 中,使装饰器得以实现的机制是 一等函数闭包

1. 函数只是堆上分配的对象

  • 在 C 中,函数是 .text 段中的指令块。
  • 在 Python 中,函数是一个完整的对象(PyObject 结构),驻留在堆上。

因为它是对象,你可以:

  • 将它赋值给变量,
  • 将它作为参数传递给其他函数,
  • 从另一个函数返回它。

把函数当作数据处理的能力是元编程的基石。

2. 引擎:闭包

如果你来自 C++,你会知道局部变量在函数的栈帧被弹出时就会消亡。Python 则不同。当内部函数引用了外层作用域的变量时,Python 编译器会注意到并 提升 该变量——把它从普通的栈项变成堆上的 cell 对象

即使外层函数已经返回,内部函数仍然保留对该 cell 对象的引用。这种“被记住的环境”称为 闭包

闭包是一个函数,即使在外层函数执行完毕后,仍然记得其封闭作用域中的变量。

装饰器完全依赖闭包来记住它们包装的 哪个 函数。

第 2 部分:构建模式

装饰器本质上非常简单:它是一个接受函数作为输入并返回新函数作为输出的函数。

手动装饰(原始模式)

# The decorator factory
def my_decorator(target_func):
    # The wrapper closure retains access to 'target_func'
    def wrapper():
        print(">>> Before execution")
        target_func()               # Calling the original function
        print(">> Before execution

执行核心逻辑…

注意: 在生产环境中,优先使用 Python 内置的 functools.lru_cache,而不是自行实现,因为它能够处理缓存边界,防止内存泄漏。

总结

装饰器并非魔法。它们是 一等函数闭包 的优雅应用。通过理解 Python 如何在堆上处理作用域和对象生命周期,你就获得了修改行为、注入逻辑以及干净、明确地优化性能的能力。

0 浏览
Back to Blog

相关文章

阅读更多 »