Dav*_*vid 56 python yield python-3.x
考虑以下代码:
def mygen():
yield (yield 1)
a = mygen()
print(next(a))
print(next(a))
Run Code Online (Sandbox Code Playgroud)
输出结果:
1
None
Run Code Online (Sandbox Code Playgroud)
口译员到底在“外部”做什么?
che*_*ner 49
a
是一个生成器对象。第一次调用next
它时,主体将被评估为第一个yield
表达式(即第一个要评估的表达式:内部表达式)。这yield
产生价值1
的next
回归,然后阻塞,直到下一个进入发电机。由第二次调用产生的next
,这并没有发送任何值到所述发电机。结果,第一个(内部)yield
计算为None
。该值用作外部变量的参数yield
,它成为对的第二次调用的返回值next
。如果您next
第三次打电话,您将获得一个StopIteration
例外。
比较send
方法的使用(而不是next
)来更改第一个yield
表达式的返回值。
>>> a = mygen()
>>> next(a)
1
>>> a.send(3) # instead of next(a)
3
>>> next(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Run Code Online (Sandbox Code Playgroud)
编写生成器的更明确的方式是
def mygen():
x = yield 1
yield x
a = mygen()
print(a.send(None)) # outputs 1, from yield 1
print(a.send(5)) # makes yield 1 == 5, then gets 5 back from yield x
print(a.send(3)) # Raises StopIteration, as there's nothing after yield x
Run Code Online (Sandbox Code Playgroud)
在Python 2.5之前的版本中,该yield
语句提供了调用者和生成器之间的单向通信。调用next
将执行生成器,直到下一条yield
语句为止,而yield
关键字提供的值将作为的返回值next
。生成器还将在yield
语句的点处挂起,等待下一个调用next
恢复。
在Python 2.5时,yield
语句置换*与yield
表达,和发电机获取的send
方法。send
的工作方式非常类似于next
,但可以接受一个参数。(对于其余部分,假定next(a)
等效于a.send(None)
。)生成器在调用之后开始执行send(None)
,此时它执行直到第一个生成为止yield
,该生成器将像以前一样返回一个值。不过,现在表达式将一直阻塞,直到下一次调用send
,此时yield
表达式的计算结果将是传递给的参数send
。生成器现在可以在恢复时接收值。
*尚未完全取代;kojiro的答案更详细地说明了yield
语句和yield
表达式之间的细微差别。
koj*_*iro 25
yield
有两种形式,表达式和语句。它们基本上是相同的,但我最经常statement
以不使用结果的形式查看它们。
def f():
yield a thing
Run Code Online (Sandbox Code Playgroud)
但是在表达式形式中,yield
具有一个值:
def f():
y = yield a thing
Run Code Online (Sandbox Code Playgroud)
在您的问题中,您同时使用两种形式:
def f():
yield ( # statement
yield 1 # expression
)
Run Code Online (Sandbox Code Playgroud)
迭代生成的生成器时,首先将获得内部yield表达式的结果
>>> x=f()
>>> next(x)
1
Run Code Online (Sandbox Code Playgroud)
此时,内部表达式还产生了一个值,外部语句可以使用该值
>>> next(x)
>>> # None
Run Code Online (Sandbox Code Playgroud)
现在您已经用尽了发电机
>>> next(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Run Code Online (Sandbox Code Playgroud)
要了解有关语句和表达式的更多信息,在其他stackoverflow问题中也有很好的答案:表达式和Python中的语句之间有什么区别?