有关类似问题的一些好问题,例如:
python generator "send" function purpose?
What does the "yield" keyword do?
让我们回到“发送”的定义:
恢复执行并将值“发送”到生成器函数中 . value参数成为当前yield表达式的结果 . send()方法返回生成器产生的下一个值,如果生成器退出而不产生另一个值,则引发StopIteration . 当调用send()来启动生成器时,必须使用None作为参数调用它,因为没有可以接收值的yield表达式
但我觉得我错过了一些重要的东西 . 这是我的3 send
调用的示例,包括初始化生成器的初始值为 None
的值:
def multiplier():
while True:
m = yield # Line #3
print('m = ' + str(m)) # Line #4
yield str(m * 2) # Line #5
yield str(m * 3) # Line #6
#------------------------
it = multiplier()
print('it.send(None): ')
print(str(it.send(None)))
print('--------------')
print('it.send(10): ')
print(it.send(10))
print('--------------')
print('it.send(100): ')
print(it.send(100))
print('--------------')
这是一个输出:
it.send(None):
None
--------------
it.send(10):
m = 10
20
--------------
it.send(100):
30
--------------
Questions:
-
当我在第5行使用
it.send(10)
时会发生什么 . 如果我们遵循定义,则恢复生成器执行 . Generator接受10
作为输入值,并在当前yield expression
中使用它 . 在我的例子中是yield str(m * 2)
,但是m
如何设置为10
. 什么时候发生的 . 那是因为m
和yield
之间在#3行中的引用? -
在第6行
it.send(10)
中发生了什么,为什么输出仍然是30
?这是否意味着我之前的问题中的参考只能使用一次?
Note: 如果我稍微更改我的示例并在第5行和第6行之间添加一行 m = yield
然后在 print(it.send(10))
之后使用 next(it)
- 在这种情况下输出开始有意义:20和300
1 回答
您的生成器函数有三个
yield
表达式,但是're throwing away the value from two of them (lines 5 and 6). If you did something with the values there, you' d看到函数中使用的100
. 如果您继续运行示例,则第五次调用send
将导致生成器将m
更新为新值 .让我们在您的示例中查看执行
send
调用的代码,并查看生成器同时执行的操作:此时,生成器对象已创建并保存到
it
. 生成器代码还没有开始运行,它是_2388701的代码 .这开始运行生成器函数的代码 . 发送的值必须是
None
或者'll get an error. The function never sees that value. It'更常见的是使用next
来启动发生器,因为next(it)
相当于it.send(None)
.生成器函数一直运行到第3行,第一个
yield
出现在第3行 . 由于您没有产生任何特定值,因此send
的返回值为None
(将被打印) .这个值被发送到生成器并成为第3行
yield
表达式的值 . 所以10
被存储为m
,代码在第4行打印出来 . 生成器函数继续运行到第5行,它到达下一行yield
表达 . 由于它正在产生str(m * 2)
,调用代码得到"20"
并打印出来 .100值作为第23行
yield
的值发送到生成器中 . 该值被忽略,因为您没有将yield
用作表达式而是用作语句 . 就像将100
单独放在一条线上一样,这是完全合法的,但可能不是很有用 . 代码继续到第5行,它产生str(m * 3)
或"30"
,它由调用代码打印 .这就是你的驱动代码停止的地方,但是生成器仍处于活动状态,你可以向它发送更多的值(并获得更多的值) . 你对发生器的下一个值也会被忽略,就像
100
那样,但是当生成器中的while
循环返回到顶部并且达到第3行yield
时,之后的值将以新的m
值结束 .我怀疑你在这段代码中对
send
的一些困惑与你使用yield
作为表达式和语句的事实有关 . 可能你不关心发送到发生器的所有值,或者你不关心它们中的任何一个 . 如果要同时生成多个值(如n*2
和n*3
),则可以生成元组而不是单个项 .这是您的代码的修改版本,我认为您可能更容易玩和理解: