python yield 函数是如何工作的?
How does this python yield function work?
def func():
output = 0
while True:
new = yield output
output = new
genr = func()
print(next(genr))
print(next(genr))
print(next(genr))
输出:
0
None
None
我想的是:
genr=func()
return 一个生成器,但实际上 运行 不是它。
- first
print(next(genr))
运行 从 func 开始到 yield output
,但还没有分配回 new
,所以输出 0
是有意义的。
- 第二个
print(next(genr))
从将output
赋值回new
开始,下一行output = new
将output
和new
都赋值为0 ,接下来执行yield output
应该return0,但为什么它return None
实际上?
yield expression is the value sent in by the generator.send() 函数的结果,next(gen)
等同于 gen.send(None)
。因此,每次调用 next()
时,new
都会收到值 None
。
如果改为这样做:
gen = func()
print(next(gen)) # gets the first value of 'output'
print(next(gen)) # send in None, get None back
print(gen.send(10)) # send in 10, get 10 back
print(gen.send(20)) # send in 20, get 20 back
你会得到这个输出:
0
None
10
20
A yield 语句像 return 一样用于 return 一个值,但它不会破坏堆栈帧(部分知道当前行、局部变量和未决 try-statements) 的函数。这样可以让函数在yield后恢复。
当您调用一个包含 yield 的函数时,它 return 是一个 "generator" 允许您 运行 代码直到一个 yield 然后从它停止的地方恢复它。
>>> def squares(n):
for i in range(n):
yield i ** 2
>>> g = squares(5) # create the generator
>>> g
<generator object squares at 0x106beef10>
>>> next(g) # run until the first yield
0
>>> next(g) # resume after the yield
1
>>> next(g) # resume after the yield
4
>>> next(g) # resume after the yield
9
>>> next(g) # resume after the yield
16
>>> next(g) # looping is terminated with a StopIteration
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
next(g) # looping is terminated with a StopIteration
StopIteration
有趣的是,生成器可以使用 send() 方法接受值。要为这种发电机启动泵,第一个调用应该是 next().
>>> def capitalize():
word = 'start'
while word != 'quit':
word = yield word.capitalize()
>>> g = capitalize()
>>> next(g) # run to the first yield
'Start'
>>> g.send('three') # send in a value to be assigned to word
'Three'
>>> g.send('blind') # send in a value to be assigned to word
'Blind'
>>> g.send('mice') # send in a value to be assigned to word
'Mice'
>>> g.send('quit') # send in a control value
Traceback (most recent call last):
File "<pyshell#28>", line 1, in <module>
g.send('quit') # send in a control value
StopIteration
你的例子中 figured-out 是 next(g)
与 g.send(None)
相同。
以下是the docs要说的:
The value of the yield expression after resuming depends on the method
which resumed the execution. If __next__() is used (typically via
either a for or the next() builtin) then the result is None.
Otherwise, if send() is used, then the result will be the value passed
in to that method
这里有一个 session 让所有这些都可见:
>>> def show_expression():
for i in range(5):
word = yield 10
print('The word is %r' % word)
>>> g = show_expression()
>>> next(g)
10
>>> g.send('blue')
The word is 'blue'
10
>>> g.send('no')
The word is 'no'
10
>>> g.send('yellow')
The word is 'yellow'
10
>>> next(g)
The word is None
10
>>> g.send('done')
The word is 'done'
Traceback (most recent call last):
File "<pyshell#44>", line 1, in <module>
g.send('done')
StopIteration
希望从第一原理中解释所有的奥秘:-)
def func():
output = 0
while True:
new = yield output
output = new
genr = func()
print(next(genr))
print(next(genr))
print(next(genr))
输出:
0
None
None
我想的是:
genr=func()
return 一个生成器,但实际上 运行 不是它。- first
print(next(genr))
运行 从 func 开始到yield output
,但还没有分配回new
,所以输出0
是有意义的。 - 第二个
print(next(genr))
从将output
赋值回new
开始,下一行output = new
将output
和new
都赋值为0 ,接下来执行yield output
应该return0,但为什么它returnNone
实际上?
yield expression is the value sent in by the generator.send() 函数的结果,next(gen)
等同于 gen.send(None)
。因此,每次调用 next()
时,new
都会收到值 None
。
如果改为这样做:
gen = func()
print(next(gen)) # gets the first value of 'output'
print(next(gen)) # send in None, get None back
print(gen.send(10)) # send in 10, get 10 back
print(gen.send(20)) # send in 20, get 20 back
你会得到这个输出:
0
None
10
20
A yield 语句像 return 一样用于 return 一个值,但它不会破坏堆栈帧(部分知道当前行、局部变量和未决 try-statements) 的函数。这样可以让函数在yield后恢复。
当您调用一个包含 yield 的函数时,它 return 是一个 "generator" 允许您 运行 代码直到一个 yield 然后从它停止的地方恢复它。
>>> def squares(n):
for i in range(n):
yield i ** 2
>>> g = squares(5) # create the generator
>>> g
<generator object squares at 0x106beef10>
>>> next(g) # run until the first yield
0
>>> next(g) # resume after the yield
1
>>> next(g) # resume after the yield
4
>>> next(g) # resume after the yield
9
>>> next(g) # resume after the yield
16
>>> next(g) # looping is terminated with a StopIteration
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
next(g) # looping is terminated with a StopIteration
StopIteration
有趣的是,生成器可以使用 send() 方法接受值。要为这种发电机启动泵,第一个调用应该是 next().
>>> def capitalize():
word = 'start'
while word != 'quit':
word = yield word.capitalize()
>>> g = capitalize()
>>> next(g) # run to the first yield
'Start'
>>> g.send('three') # send in a value to be assigned to word
'Three'
>>> g.send('blind') # send in a value to be assigned to word
'Blind'
>>> g.send('mice') # send in a value to be assigned to word
'Mice'
>>> g.send('quit') # send in a control value
Traceback (most recent call last):
File "<pyshell#28>", line 1, in <module>
g.send('quit') # send in a control value
StopIteration
你的例子中 figured-out 是 next(g)
与 g.send(None)
相同。
以下是the docs要说的:
The value of the yield expression after resuming depends on the method which resumed the execution. If __next__() is used (typically via either a for or the next() builtin) then the result is None. Otherwise, if send() is used, then the result will be the value passed in to that method
这里有一个 session 让所有这些都可见:
>>> def show_expression():
for i in range(5):
word = yield 10
print('The word is %r' % word)
>>> g = show_expression()
>>> next(g)
10
>>> g.send('blue')
The word is 'blue'
10
>>> g.send('no')
The word is 'no'
10
>>> g.send('yellow')
The word is 'yellow'
10
>>> next(g)
The word is None
10
>>> g.send('done')
The word is 'done'
Traceback (most recent call last):
File "<pyshell#44>", line 1, in <module>
g.send('done')
StopIteration
希望从第一原理中解释所有的奥秘:-)