考虑以下代码:
def mygen():
yield (yield 1)
a = mygen()
print(next(a))
print(next(a))
产出产出:
1
None
翻译在“外部”到底做了什么?
发布于 2019-04-30 06:04:18
a
是一个生成器对象。当您第一次在它上调用next
时,将对主体进行求值,直到第一个yield
表达式(即第一个要计算的表达式:内部表达式)。该yield
生成next
返回的值1
,然后阻塞,直到下一个条目进入生成器。这是对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
编写生成器的一个更明确的方法应该是
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
在Python2.5之前,yield
语句在调用方和生成器之间提供单向通信;对next
的调用将在下一个yield
语句之前执行生成器,而yield
关键字提供的值将充当next
的返回值。生成器还将在yield
语句的点处挂起,等待下一次对next
的调用恢复。
在Python2.5中,yield
语句被替换为yield
表达式,生成器获得了一个send
方法。send
的工作原理非常类似于next
,只不过它可以使用一个参数。(对于其余部分,假设next(a)
等同于a.send(None)
)。生成器在调用send(None)
之后开始执行,此时它一直执行到第一个yield
,后者像以前一样返回一个值。但是,现在,表达式一直阻塞到下一次对send
的调用,此时yield
表达式将计算为传递给send
的参数。生成器现在可以在恢复时接收值。
*没有完全被替换;kojiro的回答更详细地说明了yield
语句和yield
表达式之间的细微差别。
发布于 2019-04-30 06:11:22
yield
有两种形式,表达和陈述。它们大多是相同的,但我经常在statement
表单中看到它们,在那里不会使用结果。
def f():
yield a thing
但是在表达式形式中,yield
有一个值:
def f():
y = yield a thing
在你的问题中,你使用了这两种形式:
def f():
yield ( # statement
yield 1 # expression
)
当您在结果生成器上迭代时,首先得到内部屈服表达式的结果。
>>> x=f()
>>> next(x)
1
此时,内部表达式还产生了外部语句可以使用的值。
>>> next(x)
>>> # None
现在你用光了发电机
>>> next(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
要了解关于语句和表达式的更多信息,在其他堆栈溢出问题中有很好的答案:Python中的表达式和语句有什么区别?
发布于 2019-04-30 06:03:44
>>> def mygen():
... yield (yield 1)
...
>>> a = mygen()
>>>
>>> a.send(None)
1
>>> a.send(5)
5
>>> a.send(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
>>>
>>>
>>> def mygen():
... yield 1
...
>>> def mygen2():
... yield (yield 1)
...
>>> def mygen3():
... yield (yield (yield 1))
...
>>> a = mygen()
>>> a2 = mygen2()
>>> a3 = mygen3()
>>>
>>> a.send(None)
1
>>> a.send(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> a2.send(None)
1
>>> a2.send(0)
0
>>> a2.send(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> a3.send(None)
1
>>> a3.send(0)
0
>>> a3.send(1)
1
>>> a3.send(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
其他的产量只是等待一个值被传递给,生成器不仅提供数据,而且还接收数据。
>>> def mygen():
... print('Wait for first input')
... x = yield # this is what we get from send
... print(x, 'is received')
...
>>> a = mygen()
>>> a.send(None)
Wait for first input
>>> a.send('bla')
bla is received
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
如果得到下一个值,则yield
将在继续时给出下一个值,如果它不用于给出下一个值,则用于接收下一个值。
>>> def mygen():
... print('Wait for first input')
... x = yield # this is what we get from send
... yield x*2 # this is what we give
...
>>> a = mygen()
>>> a.send(None)
Wait for first input
>>> a.send(5)
10
>>>
https://stackoverflow.com/questions/55922302
复制