在Python 3.3+;中使用新生成器调用gen.send();?

在Python 3.3+;中使用新生成器调用gen.send();?,python,python-3.x,generator,yield-keyword,Python,Python 3.x,Generator,Yield Keyword,发件人: 由于生成器迭代器从生成器函数体的顶部开始执行,因此在刚刚创建生成器时,没有接收值的屈服表达式。因此,当生成器迭代器刚刚启动时,禁止使用非None参数调用send() 比如说, >>> def a(): ... for i in range(5): ... print((yield i)) ... >>> g = a() >>> g.send("Illegal") Traceback (most recent

发件人:

由于生成器迭代器从生成器函数体的顶部开始执行,因此在刚刚创建生成器时,没有接收值的屈服表达式。因此,当生成器迭代器刚刚启动时,禁止使用非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
>>定义a():
...     对于范围(5)中的i:
...         印刷品((收益率i))
... 
>>>g=a()
>>>g.发送(“非法”)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:无法向刚启动的生成器发送非None值
为什么这是非法的?我在这里理解了
yield
的用法,它暂停函数的执行,并在下次调用
next()
(或
send()
)时返回到该位置。但是打印
(收益率i)
的第一个结果似乎是合法的

以另一种方式询问,生成器“g”在什么状态下直接位于
g=a()
之后。我假设它在第一次生成之前一直运行
a()

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

注意:我已经阅读了的答案,但它并没有真正触及为什么在新的生成器上调用send(非None)是非法的

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

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

这是您在问题中引用的内容:“因为生成器迭代器从生成器函数体的顶部开始执行…”中也提到了这一点,其中引入了生成器:

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

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

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


如果在yield语句之前还没有执行,如何返回生成器?如果if语句中有收益,而else语句没有收益,该怎么办?“如果在yield语句之前还没有执行,那么如何返回生成器?”为什么会有问题?@StephenM347:你读过政治公众人物吗?函数中任何一个屈服点的存在都使函数成为生成函数。执行率是否永远达不到收益率并不重要。函数的生成器属性是在函数定义时确定的,在它的任何代码实际执行之前。@BrenBarn,你在那里的最后一条评论真的触及了我误解的核心!我确实读了很多政治公众人物的文章,但我并没有找到任何描述它的部分。如果你把最后的评论写在答案里,我会把它标记为正确的。还有,我试了一下,有没有办法从最初返回的生成器中获取值3?@StephenM347:看看你的例子,我知道你的意思是,你可以从生成器内部的
return 3
中获取值3,而不是提升StopIteration。答案也是否定的。在生成器中,
yield
是生成值的方法。如果您返回一个值,该值将成为StopIteration的参数(这就是为什么您第一次尝试时得到
StopIteration:3
)。你不能有一个函数,有时是生成器,有时不是;要么是,要么不是,这取决于定义的时间。