Python 3:生成器的发送方法 [英] Python 3: send method of generators
问题描述
我听不懂send
方法.我了解它用于操作发电机.但
语法在这里:generator.send(value)
.
I can't understand the send
method. I understand that it is used to operate the generator. But
the syntax is here: generator.send(value)
.
我不知为何无法理解为什么该值应成为当前yield
表达式的结果.我准备了一个例子:
I somehow can't catch why the value should become the result of the current yield
expression. I prepared an example:
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
坦率地说,这让我感到惊讶.
Well, frankly speaking, it is astonishing me.
- 在文档中我们可以看到,执行
yield
语句时,生成器的状态被冻结,并且expression_list
的值返回给next
的调用方. 好吧,这似乎没有发生.为什么我们要在gen()
中执行if
语句和print
函数. - 我如何理解功能内外的
X
为什么不同? 好的.让我们假设send(77)
将77传输到m
中.好吧,yield
表达式变成77. 那么X = yield i
是什么?而函数内部的77如何在外部发生时转换为5? - 为什么第一个结果字符串不能反映生成器内部发生的任何事情?
- In the documentation we can read that when a
yield
statement is executed, the state of the generator is frozen and the value ofexpression_list
is returned tonext
‘s caller. Well, it doesn't seem to have happened. Why can we executeif
statement andprint
function insidegen()
. - How can I understand why
X
inside and outside the function differs? Ok. Let us assume thatsend(77)
transmits 77 intom
. Well,yield
expression becomes 77. Then what isX = yield i
? And how 77 inside the function converts into 5 when occurs outside? - Why the first result string doesn't reflect anything that is going on inside the generator?
无论如何,您能以某种方式对这些send
和yield
语句发表评论吗?
Anyway, could you somehow comment on these send
and yield
statements?
推荐答案
在生成器中使用send
和表达式yield
时,会将其视为协程.一个单独的执行线程,可以按顺序交错运行,但不能与其调用者并行运行.
When you use send
and expression yield
in a generator, you're treating it as a coroutine; a separate thread of execution that can run sequentially interleaved but not in parallel with its caller.
当调用者执行R = m.send(a)
时,它将对象a
放入生成器的输入插槽中,将控制权移交给生成器,然后等待响应.生成器将接收对象a
作为X = yield i
的结果,并运行直到遇到另一个yield
表达式,例如Y = yield j
.然后,它将j
放入其输出插槽,将控制权转回调用方,并等待直到再次恢复.调用方收到j
作为R = m.send(a)
的结果,并一直运行直到命中另一个S = m.send(b)
语句,依此类推.
When the caller executes R = m.send(a)
, it puts the object a
into the generator's input slot, transfers control to the generator, and waits for a response. The generator receives object a
as the result of X = yield i
, and runs until it hits another yield
expression e.g. Y = yield j
. Then it puts j
into its output slot, transfers control back to the caller, and waits until it gets resumed again. The caller receives j
as the result of R = m.send(a)
, and runs until it hits another S = m.send(b)
statement, and so on.
R = next(m)
与R = m.send(None)
相同;它将None
放入生成器的输入插槽中,因此,如果生成器检查X = yield i
的结果,则X
将为None
.
R = next(m)
is just the same as R = m.send(None)
; it's putting None
into the generator's input slot, so if the generator checks the result of X = yield i
then X
will be None
.
作为一个比喻,考虑使用哑巴服务员:
As a metaphor, consider a dumb waiter:
当服务器从客户那里收到订单时,他们将垫子放在笨拙的服务员中,send
放到厨房,然后在舱口旁等待菜品:
When the server gets an order from a customer, they put the pad in the dumb waiter, send
it to the kitchen, and wait by the hatch for the dish:
R = kitchen.send("Ham omelette, side salad")
厨师(一直在舱口旁等待)拿起订单,准备菜肴,yield
将其送到餐厅,然后等待下一个订单:
The chef (who's been waiting by the hatch) picks up the order, prepares the dish, yield
s it to the restaurant, and waits for the next order:
next_order = yield [HamOmelette(), SideSalad()]
服务器(一直在舱口旁等待)将菜带给客户,然后再下单,以此类推.
The server (who's been waiting by the hatch) takes the dish to the customer and returns with another order, etc.
由于服务器和厨师都在send
下达订单或yield
下完菜后在舱口旁等待,所以任何时候只有一个人在做任何事情,即该过程是单线程的.双方都可以使用正常的控制流,因为发电机机械(哑服务员)负责交错执行.
Because both the server and chef wait by the hatch after send
ing an order or yield
ing a dish, there's only one person doing anything at any one time i.e. the process is single threaded. Both sides can use normal control flow, as the generator machinery (the dumb waiter) takes care of interleaving execution.
这篇关于Python 3:生成器的发送方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!