为什么 Python 的 yield 语句不能在一个函数中调用,也不能在它调用的另一个函数中调用,为什么在尝试时没有报告错误?

Why can Python's yield statement not be called in a function and also in another function that it calls and why no error reported when attempted?

我是 Python 的新手,我发现 yield 语句非常有用。然而,有件事让我吃惊。在函数中放置多个 yield 语句将导致每个语句都出现在 for var in fn() 循环中。但是,如果我从使用 yield 语句的初始函数执行另一个函数,则不会执行该函数。我只是采用了天真的方法,只是认为它会起作用。

例如

def fn2():
    print("blah")
    yield "you"
    
def fn():
    yield "hi"
    fn2()
    yield "there"
    
for a in fn():
    print('{}'.format(a))

如果我注释掉 yield "you",我的输出将是:

hi
there

如果不是,那就是:

hi
blah
there

Demo

没有任何警告或任何类型的错误,它只是耸了耸肩并继续执行,这比它不起作用更令人惊讶。

这是怎么回事?

具有 yield 的函数是 生成器 。它们总是产生一个可迭代对象,即使其中只有一个 yield 语句。

为了获得函数产生的值,您必须迭代。

您可以使用 for v in fn2: yield v,但 Python 也有一个方便的语句:yield from

def fn2():
    print("blah")
    yield "you"
    
def fn():
    yield "hi"
    yield from fn2()
    yield "there"
    
for a in fn():
    print('{}'.format(a))

Python 的生成器是惰性求值的。创建一个(在本例中 "调用 fn2")不会启动迭代。这就是为什么 fn2 似乎甚至没有被调用的原因。它被称为。

将其 return 值想象成 fn2 函数体第一行之前的书签。一旦您真正开始迭代,“书签”将前进到第一个 yield 语句,依此类推,直到函数结束。