Python 3:生成器的发送方法
我无法理解Python 3:生成器的发送方法,python,python-3.x,generator,Python,Python 3.x,Generator,我无法理解send方法。我知道它是用来操作发电机的。但是 语法如下:generator.send(value) 我不知怎么搞不明白为什么这个值应该成为当前yield表达式的结果。我准备了一个例子: def gen(): for i in range(10): X = yield i if X == 'stop': break print("Inside the function " + str(X)) m = ge
send
方法。我知道它是用来操作发电机的。但是
语法如下:generator.send(value)
我不知怎么搞不明白为什么这个值应该成为当前yield
表达式的结果。我准备了一个例子:
def gen():
for i in range(10):
X = yield i
if X == 'stop':
break
print("Inside the function " + str(X))
m = gen()
print("1 Outside the function " + str(next(m)) + '\n')
print("2 Outside the function " + str(next(m)) + '\n')
print("3 Outside the function " + str(next(m)) + '\n')
print("4 Outside the function " + str(next(m)) + '\n')
print('\n')
print("Outside the function " + str(m.send(None)) + '\n') # Start generator
print("Outside the function " + str(m.send(77)) + '\n')
print("Outside the function " + str(m.send(88)) + '\n')
#print("Outside the function " + str(m.send('stop')) + '\n')
print("Outside the function " + str(m.send(99)) + '\n')
print("Outside the function " + str(m.send(None)) + '\n')
结果是:
1 Outside the function 0
Inside the function None
2 Outside the function 1
Inside the function None
3 Outside the function 2
Inside the function None
4 Outside the function 3
Inside the function None
Outside the function 4
Inside the function 77
Outside the function 5
Inside the function 88
Outside the function 6
Inside the function 99
Outside the function 7
Inside the function None
Outside the function 8
坦白说,这让我很吃惊
yield
语句时,生成器的状态被冻结,并且expression\u list
的值被返回给next
的调用者。
嗯,这似乎没有发生。为什么我们可以在gen()
中执行if
语句和print
函数李>
send(77)
将77传输到m
。嗯,yield
表达式变成77。
那么什么是X=yield i
?当函数外部发生时,函数内部的77如何转换为5无论如何,你能对这些
send
和yield
语句发表评论吗?当你在生成器中使用send
和表达式yield
时,你将其视为一个协同程序;一个单独的执行线程,可以顺序交错运行,但不能与其调用方并行运行
当调用方执行R=m.send(a)
时,它将对象a
放入生成器的输入槽中,将控制权转移给生成器,并等待响应。生成器接收对象a
,作为X=yield i
的结果,并运行直到它碰到另一个yield
表达式,例如Y=yield j
。然后它将j
放入其输出槽中,将控制权转移回调用者,并等待它再次恢复。调用方收到R=m.send(a)
的结果j
,并运行直到它碰到另一个S=m.send(b)
语句,依此类推
R=next(m)
与R=m.send(None)
完全相同;它将None
放入生成器的输入插槽,因此如果生成器检查X=yield i
的结果,则X
将为None
作为隐喻,考虑A:
当服务员收到顾客的订单时,他们把便笺簿放在哑侍者的肚子里,把它送到厨房,然后在舱口等菜:
R = kitchen.send("Ham omelette, side salad")
厨师(一直在舱口旁等待)拿起订单,准备菜肴,yield
s将其送到餐厅,然后等待下一个订单:
next_order = yield [HamOmelette(), SideSalad()]
服务员(一直在舱口等着)把盘子拿给顾客,然后带着另一份订单回来,等等
因为在发送一份订单或下一道菜后,服务员和厨师都会在舱口等待,所以在任何时候只有一个人在做任何事情,即该过程是单线程的。双方都可以使用正常的控制流,因为生成器机器(哑侍者)负责交错执行
def gen():
i = 1
while True:
i += 1
x = yield i
print(x)
m = gen()
next(m)
next(m)
m.send(4)
结果
None
4
请查看上面更多的简化代码。
我认为导致你困惑的是“x=收益率I”陈述,
这句话并不是说从send()方法接受的值被关联到i,然后我被关联到x。
相反,值i由yield station返回给生成器,x由send()方法生成。一条语句同时做两件事。最容易混淆的部分应该是这一行x=yield i
,特别是在生成器上调用send()
时。实际上,你唯一需要知道的是:
在词汇层面:
next()
等于send(None)
在口译员级别:
X=收益率i
等于以下几行(订单事项):
和2条注释是确切的原因,为什么我们需要第一次调用<代码>发送(没有)>代码>,因为生成器会返回<代码> i>代码(屈服<代码> i>代码> <强> < < /强> >将值分配给<代码> x< /代码>
,因为您甚至征求意见,请考虑以下情况:
def lambda_maker():
def generator():
value = None
while 1:
value = yield value
value= value[0][1]
f = generator()
next(f) # skip the first None
return f.send # a handy lambda value: value[0][1]
现在,以下两行是等效的:
a_list.sort(key=lambda a: a[0][1])
a_list.sort(key=lambda_maker())
(顺便提一下,在当前(2018-05-26,GDPR后第1天)☺) 在CPython2和CPython3实现中,第二行比第一行运行得更快,但这是与每次函数调用的帧对象初始化开销相关的细节。)
这里发生了什么?lambda\u maker
调用f=generator()
并获取一个生成器;调用初始值next(f)
开始运行生成器并使用初始的None
值,并在yield
行暂停。然后它将绑定方法f.send
返回给调用方。从这一点开始,每次调用此绑定方法时,generator.value
local都会收到绑定方法的参数recalculatesvalue
然后循环返回yield
ingvalue
的当前值,并等待下一个。send
获取另一个值
生成器对象保留在内存中,它在循环中所做的一切是:
- 产生当前结果(最初无)
- 接收另一个值(任何人用作
.send
参数的值)
- 根据接收到的值重新计算当前结果
- 回环
注意:
为了简单起见,我的回答仅限于生成器每行最多有1个
yield
命令的情况
TL;DR:
.send()
方法:
- 将值发送到当前挂起的命令,但<
a_list.sort(key=lambda a: a[0][1])
a_list.sort(key=lambda_maker())
received_1 = yield "first_from_iterator"
result = math.cos((yield "first_from_iterator") * math.pi) # result: -1
g.send(1) # Not very appropriate
from_iterator_2 = g.send(1) # Saving the 2nd yielded value