Python 3:发送器的发送方法
我无法理解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_list
的值被返回给next
调用者。 好吧,它似乎并没有发生。 为什么我们可以执行if
语句并print
内部功能gen()
X
区别? 好。 让我们假设send(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
放入其输出插槽,将控制转回给调用者,并等待再次恢复。 调用者接收j
作为R = m.send(a)
,并运行直至遇到另一个S = m.send(b)
语句,依此类推。
R = next(m)
与R = m.send(None)
; 它将None
放入发生器的输入槽,所以如果发生器检查X = yield i
的结果,那么X
将是None
。
作为一个比喻,考虑一个愚蠢的服务员:
当服务员接到客户的订单时,他们把垫放在哑巴服务员的手中, send
它送到厨房,然后在舱口等候这道菜:
R = kitchen.send("Ham omelette, side salad")
厨师(谁一直在等待通过舱口)拿起顺序,准备的菜, yield
是S到餐厅,并等待下一个命令:
next_order = yield [HamOmelette(), SideSalad()]
服务器(已经在舱口等待)将餐具拿到顾客处,并用另一个订单返回等等。
因为服务员和厨师在send
订单或yield
一道菜后等待孵化器,所以只有一个人在任何时间做任何事情,即该过程是单线程的。 双方都可以使用正常的控制流程,因为发电机组(愚蠢的服务员)负责交错执行。
最令人困惑的部分应该是这行X = yield i
,特别是当你在发生器上调用send()
时。 其实你唯一需要知道的是:
在词汇层次上: next()
等于send(None)
在解释者层面: X = yield i
等于线下( 订货物 ):
yield i
# won't continue until next() or send() is called
# and this is also the entry point of next() or send()
X = the_input_of_send
并且,这两行注释是确切的原因,为什么我们需要第一次调用send(None)
,因为生成器会在将值赋给X
之前返回i
(yield i
)
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 = yield i'的表述,这个表述并不是说从send()方法接受的值被分配给了我,然后我被分配给了x。 相反,价值我通过yield statment返回到生成器,x通过send()方法来分裂。一个语句同时做两件事。