You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

装饰器无需显式调用即可注册函数的原理探究

搞懂装饰器的执行时机:你误解的不是特例,是Python的底层规则

首先得给你纠正一个关键认知:装饰器根本不是在函数显式调用时才生效的,而是在函数定义的那一刻就执行了——这是Python装饰器的核心工作机制,不是什么特例。

先拆解你代码里的逻辑

你写的@register其实是Python的语法糖,等价于:

def say_hello(name):
    return f"Hello {name}"
say_hello = register(say_hello)

看到没?当Python解释器加载你的模块、执行到def say_hello这部分代码时,它会先定义这个函数,然后立刻调用register(say_hello),把刚定义的函数对象传进去,再把register的返回值重新赋值给say_hello。

你的register函数做的事情很简单:把传入的函数对象存到PLUGINS字典里,然后返回原函数。所以不管你之后调不调用say_hello(),这个注册动作在函数定义时就完成了——这就是为什么PLUGINS里已经有这两个函数的原因。

如果register调用了func会怎样?

假设你把register改成这样:

def register(func):
    """Register a function as a plug-in"""
    PLUGINS[func.__name__] = func
    # 新增:调用传入的函数
    print(func("测试用户"))
    return func

那当模块加载时,Python执行到@register修饰的say_hello和be_awesome时,会立刻调用这两个函数,输出:

Hello 测试用户
Yo 测试用户, together we are the awesomest!

这个时候你甚至还没调用randomly_greet,函数就已经被执行了——因为装饰器的执行时机是函数定义阶段,不是调用阶段。

这不是特例,是所有装饰器的通用规则

不管你写的装饰器是用来注册函数、做日志、加缓存还是什么其他功能,只要用了@装饰器的语法,装饰器函数都会在函数定义时被执行一次,处理被装饰的函数对象。

你之前的误解可能是把装饰器和函数调用混淆了:装饰器是用来“包装”或“处理”函数本身的,而不是等待函数被调用时才触发——函数调用是另一回事,那是你之后主动调用say_hello("Alice")的时候才会执行函数内部的逻辑。

内容的提问来源于stack exchange,提问作者Ivan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:08:59