Nico
Published on 2025-07-29 / 1 Visits
0
0

装饰器原理

Python 装饰器机制的核心!
简要来说,decorator(func)这一步,是装饰器实际发挥作用的环节。下面详细解析:


一、装饰器的本质流程

当你写:

@get("/")
def homepage():
    print("Homepage")

Python 其实做了以下事情

  1. 运行 def homepage(): ... 语句,创建函数对象 homepage
  2. 运行 get("/"),返回一个新的函数:decorator
  3. 调用 decorator(homepage),返回值(可能是原函数,也可能是新函数)赋值给名字homepage

所以最终 homepage 这个名字,大多数场合下已经不是你原来定义的函数了,而是装饰器返回的那个(包裹或者加工后的)新函数。


二、为什么 decorator(func) 能“拿到”原函数?

Python 的函数本身就是对象,你可以像变量一样传递:

def hello():
    print("hi")
x = hello         # 这时 x 和 hello 都指向同一个函数对象
x()               # 输出 hi

装饰器利用这一点,直接把原始函数对象传给装饰器的参数(如:func)。你可以对 func 做任何操作,比如记录、包裹、加工、替换。


三、装饰器执行流程图

@get("/")为例:

def get(path):
    def decorator(func):
        print(f"注册函数 {func.__name__} 到 {path}")
        return func
    return decorator

@get("/test")
def myfunc():
    print("in myfunc")

执行步骤:

  1. Python 先定义 myfunc,得到其函数对象
  2. 运行 get("/test"),得到 decorator 这个函数
  3. 调用 decorator(myfunc),把myfunc对象作为参数func传入
  4. decorator里就拿到了myfunc,可以做任何操作,比如注册、包裹等
  5. 返回值(比如原函数/包裹函数)会再次赋值给myfunc这个名字

四、简单例子验证

def outer(func):
    print("我拿到了函数对象:", func)
    return func

@outer
def foo():
    print("我是foo")

输出:

我拿到了函数对象: <function foo at 0x...>

五、装饰器的本质作用

  • 你传入的是“函数对象”,装饰器可以:
    • 登记注册(比如放到字典里)
    • 返回新函数(比如加日志、权限检查等功能,实际调用的是返回的新函数)

总结

  • decorator(func) 之所以能拿到原函数,是因为Python允许将函数对象作为参数传递;
  • 这样装饰器内部可以自由利用、操作和返回新的函数对象,达到“钩住和加工”原方法的目的,完成注册或包装等各种花式功能!

如果你还想了解装饰器和元编程更底层的原理,也可以继续问我!


Comment