0

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

所以我正在尝试创建一个将状态栏应用于生成器方法的装饰器。使用 @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)

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

进程以退出代码 0 结束

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

4

1 回答 1

0

我正在尝试自己学习这一点。使用https://stackoverflow.com/a/25827070/59867作为参考,我发现:

当您调用status_bar(TestClass().iter_range)时,它会返回您实际上并未调用的装饰函数,这就是为什么没有发生任何事情的原因。

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

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

这意味着这就是你所说的:

status_bar(TestClass.iter_range)(TestClass())
于 2021-12-17T16:47:45.957 回答