0

来自PEP342

因为生成器迭代器在生成器函数体的顶部开始执行,所以当生成器刚刚创建时,没有 yield 表达式来接收值。因此,当生成器迭代器刚刚启动时,禁止使用非 None 参数调用 send(),...

例如,

>>> def a():
...     for i in range(5):
...         print((yield i))
... 
>>> g = a()
>>> g.send("Illegal")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't send non-None value to a just-started generator

为什么这是非法的?我理解yield这里使用的方式,它暂停函数的执行,并在下次调用next()(or send()) 时返回到该位置。但似乎打印(yield i)?的第一个结果应该是合法的

换一种方式问,紧跟在 之后的生成器“g”处于什么状态g = a()。我假设它一直运行a()到第一个 yield,并且由于有一个 yield,它返回了一个生成器,而不是标准的同步对象返回。

那么,为什么在新生成器上使用非 None 参数调用 send 是非法的呢?

注意:我已经阅读了这个问题的答案,但并没有真正理解为什么在新生成器上调用 send (非 None )是非法的。

4

1 回答 1

2

换一种方式问,直接在 g = a() 之后的生成器“g”处于什么状态。我假设它一直运行 a() 直到第一个 yield,并且由于有一个 yield,它返回了一个生成器,而不是标准的同步对象返回。

不,g = a()就在函数开始之后。next(g)在您推进生成器一次(通过调用)之前,它不会运行到第一个产量。

这就是您在问题中包含的引文中所说的:“因为生成器迭代器开始在生成器函数体的顶部执行......”它也在PEP 255中说,它引入了生成器:

当调用生成器函数时,实际参数以通常的方式绑定到函数局部形式参数名称,但不会执行函数体中的代码。

请注意,是否实际执行了 yield 语句并不重要。仅yield在函数体内出现 就使函数成为生成器,如文档所述:

在函数定义中使用 yield 表达式足以使该定义创建生成器函数而不是普通函数。

于 2015-07-17T21:01:41.250 回答