在Python中装饰生成器:在yield之间调用某些方法

4

我在这里找到了有关在Python中使用yield from修饰生成函数的一些非常有用的信息。例如:

def mydec(func):
    def wrapper(*args, **kwargs):
        print(f'Getting values from "{func.__name__}"...')
        x = yield from func(*args, **kwargs)
        print(f'Got value {x}')
        return x
    return wrapper

@mydec
def mygen(n):
    for i in range(n):
        yield i

然而,这似乎仅允许在生成器生命周期的开头和结尾添加修饰行为:
>>> foo = mygen(3)
>>> x = next(foo)
Getting values from "mygen"...
>>> x
0
>>> x = next(foo)
>>> x
1
>>> x = next(foo)
>>> x
2
>>> x = next(foo)
Got value None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> x
2

我有兴趣使用装饰器来在生成器每次产生值时实现一些行为。然而,装饰器不应该修改从生成器中获取的值。例如,我希望输出结果如下:

>>> foo = mygen(3)
>>> x = next(foo)
Getting values from "mygen"...
Got value 0
>>> x
0
>>> x = next(foo)
Got value 1
>>> x
1
>>> x = next(foo)
Got value 2
>>> x
2

所以,每次yield时都会调用print,但是yield的值不变。
这种情况是否可能?
1个回答

6

yield from是用于协程的。你并没有在做协程相关的事情。只是在迭代生成器:

def mydec(func):
    def wrapper(*args, **kwargs):
        print(f'Getting values from "{func.__name__}"...')
        gen = func(*args, **kwargs)
        for value in gen:
            print(f'got value {value}')
            yield value
    return wrapper

抱歉,我想我的问题表述不够清楚。我不想让字符串成为返回值,我只是想要一些行为,例如print语句,在生成器每次yield时运行。然而,装饰器不应该修改由next()返回的值。 - corvus
好的,明白了,我看到你编辑了问题。现在它更容易了 - 那只是一个普通的for循环。 - wim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接