装饰器仅在装饰方法时起作用,但在以方法作为参数传递的方式调用装饰器时不起作用

Decorator only works when method is decorated but not when the decorator is called with method passed as argument

长期听众;第一次来电,所以如果我没有完全遵守指南,请不要开枪。

所以我正在尝试创建一个将状态栏应用于生成器方法的装饰器。我的装饰器在使用 @decorator 语法时工作得很好。然而,当调用装饰器并将方法作为参数传递时,装饰器什么都不做。我想像调用任何其他函数一样调用装饰器函数而不是使用 @status_bar 因为我想要一种可选地使用生成器的简单方法。

这是工作代码:

import time

from alive_progress import alive_bar


def status_bar(func):

    def wrapper(self):
        with alive_bar() as bar:
            for x in func(self):
                bar()

    return wrapper


class TestClass:

    def __init__(self):
        pass

    @status_bar
    def iter_range(self):
        for x in range(10000):
            time.sleep(0.01)
            yield x


TestClass().iter_range()

这会按预期在提示中生成一个状态栏。

| ▶▶▶▶▶▶▶▶▶▶▶▶▶ | ▂▂▄ 326 in 3s (98.2/s)

但是 运行 没有语法糖的代码无法执行任何操作。

def status_bar(func):

    def wrapper(self):
        with alive_bar() as bar:
            for x in func(self):
                bar()

    return wrapper


class TestClass:

    def __init__(self):
        pass

    def iter_range(self):
        for x in range(10000):
            time.sleep(0.01)
            yield x


status_bar(TestClass().iter_range)

相反,代码运行时就好像没有调用任何函数一样。

Process finished with exit code 0

我似乎总是得到相同的输出,我知道这里有一个简单的解释,这就是为什么它如此困扰我以至于我无法让它工作的原因。任何帮助是极大的赞赏。谢谢

我正在尝试自己学习。使用 作为参考,我发现:

当您调用 status_bar(TestClass().iter_range) 时,returns 您实际上并未调用的修饰函数,这就是什么都没有发生的原因。

所以类似地调用它,但只是从 class(而不是从实例)传入函数,这有效:

decorated_func = status_bar(TestClass.iter_range)
decorated_func(TestClass())

这意味着您可以这样称呼它:

status_bar(TestClass.iter_range)(TestClass())