首页 文章

在Python 3.3中将生成器与yield一起返回

提问于
浏览
42

在Python 2中,当函数定义中的return与yield一起时,出现了错误 . 但对于Python 3.3中的这段代码

def f():
  return 3
  yield 2

x = f()
print(x.__next__())

没有错误,返回用于带有yield的函数 . 但是当调用函数 __next__ 时,会抛出异常StopIteration . 为什么不只是返回值 3 ?这种回报是否被忽略了?

2 回答

  • 24

    这是Python 3.3中的一个新功能(作为注释说明,它甚至不适用于3.2) . 就像发电机中的 return 早已相当于 raise StopIteration() ,发电机中的 return <something> 现在相当于 raise StopIteration(<something>) . 因此,您看到的异常应打印为 StopIteration: 3 ,并且可以通过异常对象上的属性 value 访问该值 . 如果生成器被委托使用(也是新的) yield from 语法,那么结果就是如此 . 有关详细信息,请参阅PEP 380 .

    def f():
        return 1
        yield 2
    
    def g():
        x = yield from f()
        print(x)
    
    # g is still a generator so we need to iterate to run it:
    for _ in g():
        pass
    

    这会打印 1 ,但不打印 2 .

  • 48

    返回值不会被忽略,但生成器只会产生值, return 只会结束生成器,在这种情况下会提前结束 . 在这种情况下,推进生成器永远不会到达 yield 语句 .

    每当迭代器到达要生成的值的'end'时,必须引发 StopIteration . 发电机也不例外 . 但是,从Python 3.3开始,任何 return 表达式都会成为异常的值:

    >>> def gen():
    ...     return 3
    ...     yield 2
    ... 
    >>> try:
    ...     next(gen())
    ... except StopIteration as ex:
    ...     e = ex
    ... 
    >>> e
    StopIteration(3,)
    >>> e.value
    3
    

    使用 next() 函数来推进迭代器,而不是直接调用 .__next__()

    print(next(x))
    

相关问题