首页 > 解决方案 > Python 装饰器导入时间

问题描述

我正在一个全局集中注册我的一些函数:

# registry.py
import functools

schedule_registry = set()


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
def foo():
    print("running foo")

现在,我希望schedule_registry在导入时填写(并打印“添加...”),但令我惊讶的是:

In [1]: import registry                                                                                                                                                                                           

In [2]:  

没有打印任何内容。

问题是,如果我将装饰器更改为以下内容:

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

    return func_wrapper

@register_scheduler()
def foo():
    print("running foo")

我得到了我的期望:

In [1]: import registry                                                                                                                                                                                           
adding foo

标签: pythonimportdecorator

解决方案


这和 没有任何关系wraps

你还没有理解装饰器是如何工作的。外部函数在导入时被调用,并返回替换被修饰函数的内部函数。然后调用内部函数代替原始函数,因此需要采用其原始参数 - not func。如果您希望在导入时发生任何事情,则需要进入外部函数。

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

    @functools.wraps(func)
    def func_wrapper(*args, **kwargs):
       print(f"at call time")
       return func(*args, **kwargs)
    return func_wrapper

请注意,您的两个示例都根本不起作用;第一个不调用修饰函数,第二个在导入时调用内部函数,没有任何东西代替被修饰的函数。


推荐阅读