关于类似事项有很多好问题,例如
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
--------------
问题:
当我在第5行使用it.send(10)
时会发生什么。要是我们
按照定义,生成器执行恢复。发电机
接受10
作为输入值,并将其用于当前yield
expression
。我的示例中为yield str(m * 2)
,但后来m
设置为10
。什么时候发生的。那是因为
在#3行中m
和yield
之间的引用?
第6行it.send(10)
会发生什么,为什么输出仍为30
?
这是否意味着我之前的问题中的参考仅起作用
一旦
注意:的
如果我稍微更改我的示例并在第5行和第6行之间添加一行m = yield
,然后在next(it)
之后使用print(it.send(10))
- 在这种情况下输出开始有意义:20和300
答案 0 :(得分:2)
你的生成器函数有三个yield
表达式,但你丢掉了其中两个(第5行和第6行)的值。如果你对那里的值做了一些事情,你会看到函数中使用的100
。如果您继续运行示例,则第五次调用send
会导致生成器将m
更新为新值。
让我们在您的示例中查看执行send
调用的代码,并查看生成器同时执行的操作:
it = multiplier()
此时,生成器对象已创建并保存到it
。生成器代码尚未开始运行,它在函数代码的开头暂停。
print(str(it.send(None)))
这开始运行生成器函数的代码。发送的值必须为None
,否则您将收到错误消息。该功能永远不会看到这个价值。使用next
启动生成器更为常见,因为next(it)
等同于it.send(None)
。
生成器函数一直运行到第3行,其中出现第一个yield
。由于您没有产生任何特定值,因此send
的返回值为None
(打印出来)。
print(it.send(10))
此值将发送到生成器,并成为第3行yield
表达式的值。因此10
将存储为m
,代码将在第4行打印出来生成器函数继续运行到第5行,它到达下一个yield
表达式。由于它正在产生str(m * 2)
,因此调用代码获得"20"
并打印出来。
print(it.send(100))
100值作为第4行yield
的值发送到生成器中。该值被忽略,因为您没有使用yield
作为表达式而是作为语句。就像将100
单独放在一条线上一样,这是完全合法的,但可能不是很有用。代码继续到第5行,它产生str(m * 3)
或"30"
,由调用代码打印。
这就是你的驱动代码停止的地方,但是生成器仍处于活动状态,你可以向它发送更多的值(并获得更多的值)。您send
生成器的下一个值也会被忽略,就像100
一样,但是m
之后的值会以while
为新值yield
生成器中的循环返回到顶部,并且到达了第3行send
。
我怀疑您在此代码中与yield
的一些混淆与您使用n*2
作为表达式和语句的事实有关。可能你不想同时做这两件事。通常,您要么关心发送到生成器的所有值,要么您不关心它们中的任何值。如果您想要同时产生多个值(例如n*3
和def multiplier():
print("top of generator")
m = yield # nothing to yield the first time, just a value we get
print("before loop, m =", m)
while True:
print("top of loop, m =", m)
m = yield m * 2, m * 3 # we always care about the value we're sent
print("bottom of loop, m =", m)
print("calling generator")
it = multiplier()
print("calling next")
next(it) # this is equivalent to it.send(None)
print("sending 10")
print(it.send(10))
print("sending 20")
print(it.send(20))
print("sending 100")
print(it.send(100))
),则可以产生元组而不是单个项。
以下是您的代码的修改版本,我认为您可能更容易玩和理解:
.map