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

Python装饰器疑问:无参数装饰器导入时为何未执行注册逻辑?

为什么两种装饰器写法在模块导入时表现不同?

咱们拆解下两种装饰器的执行逻辑,就能明白为啥导入时表现天差地别了。

第一种装饰器:注册逻辑没在导入阶段触发

你第一个版本的装饰器是接收函数作为参数的普通装饰器:

def register_scheduler(func):
    @functools.wraps(func)
    def func_wrapper():
        print(f"adding {func.__name__}")
        schedule_registry.add(func)
        return func
    return func_wrapper

当用@register_scheduler装饰foo时,Python在导入模块时只会做一件事:
foo = register_scheduler(foo)
这时候register_scheduler会返回func_wrapper这个函数对象,把它赋值给foo。但注意:func_wrapper里面的打印、集合添加逻辑,只有在你主动调用foo()的时候才会执行。模块导入阶段只是完成了“把foo替换成func_wrapper”这一步,根本没触发包装函数里的代码,所以自然没输出,集合也没被填充。

第二种装饰器:注册逻辑在装饰阶段直接执行

第二个版本的装饰器是无参装饰器工厂:

def register_scheduler():
    def func_wrapper(func):
        print(f"adding {func.__name__}")
        schedule_registry.add(func)
        return func
    return func_wrapper

当用@register_scheduler()装饰foo时,Python的执行步骤变了:

  1. 先执行register_scheduler(),返回内部定义的func_wrapper函数;
  2. 紧接着用这个返回的func_wrapper去处理foo,也就是执行foo = func_wrapper(foo)。
    这时候func_wrapper里的打印和集合添加代码,是在**装饰应用的阶段(也就是模块导入时)**直接执行的——因为这一步是调用func_wrapper处理目标函数,而不是返回一个等着被调用的包装函数。所以导入模块时就会立刻打印"adding foo",集合也被正确填充了。

简单总结:

  • 第一种装饰器返回的是“待调用的包装函数”,注册逻辑要等你调用原函数才触发;
  • 第二种装饰器工厂先返回真正的装饰器,然后立刻用它处理目标函数,注册逻辑在模块加载时就跑完了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:28:54