Py学习  »  Python

Python Decorators导入时间

AdamGold • 6 年前 • 2418 次点击  

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

# 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]:  

什么都没印。

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

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
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/52047
文章 [ 2 ]  |  最新文章 6 年前
Nino Walker
Reply   •   1 楼
Nino Walker    7 年前

要完成任务:添加到集合,但不更改行为,不需要functools。相反,您只需要一个返回您的函数的简单函数。

试试这个:

schedule_registry = set()

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

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

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

print(f"now running foo..., and registry has {len(schedule_registry)} items")

foo()

你应该看到:

adding foo
adding bar
now running foo..., and registry has 2 items
running foo
Daniel Roseman
Reply   •   2 楼
Daniel Roseman    7 年前

与此无关 wraps .

你还不明白装修师是怎么工作的。在导入时调用外部函数,并返回内部函数,该函数将替换要修饰的函数。然后调用内部函数来代替原始函数,因此需要使用其原始参数- 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

请注意,这两个示例实际上都不起作用;第一个示例不调用修饰后的函数,第二个示例在导入时调用内部函数,不留下任何内容来代替要修饰的函数。