代码之家  ›  专栏  ›  技术社区  ›  corvus

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

  •  2
  • corvus  · 技术社区  · 6 年前

    我发现了一些关于在Python中装饰生成器函数的非常有用的信息 here 使用 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
    

    不过,我对每次生成器生成时使用decorator来实现某些行为很感兴趣。但是,装饰程序不应该修改从生成器获取的值。例如,我希望输出:

    >>> 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
    

    所以,打电话给 print 发生在每个屈服点,但屈服值保持不变。

    1 回复  |  直到 6 年前
        1
  •  5
  •   wim    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