我理解让步。但是生成器的send函数是做什么的呢?文件说:
generator.send(值)
恢复执行并向生成器函数“发送”一个值。value参数变成当前yield表达式的结果。send()方法返回生成器产生的下一个值,如果生成器退出而没有产生另一个值,则引发StopIteration。
这是什么意思?我以为value是生成器函数的输入?短语“send()方法返回生成器产生的下一个值”似乎也是yield的确切目的,它也返回生成器产生的下一个值。
有没有一个生成器利用send完成了yield不能完成的事情的例子?
这个函数用来写协程
def coroutine():
for i in range(1, 10):
print("From generator {}".format((yield i)))
c = coroutine()
c.send(None)
try:
while True:
print("From user {}".format(c.send(1)))
except StopIteration: pass
打印
From generator 1
From user 2
From generator 1
From user 3
From generator 1
From user 4
...
看到控件是如何来回传递的了吗?这些是协程。它们可以用于各种很酷的事情,如异步IO和类似的。
想象一下,有一个发电机,没有发送器,这是一条单行道
========== yield ========
Generator | ------------> | User |
========== ========
但是有了send,它就变成了双向的
========== yield ========
Generator | ------------> | User |
========== <------------ ========
send
这为用户打开了一扇门,用户可以动态地定制生成器的行为和生成器对用户的响应。
这个函数用来写协程
def coroutine():
for i in range(1, 10):
print("From generator {}".format((yield i)))
c = coroutine()
c.send(None)
try:
while True:
print("From user {}".format(c.send(1)))
except StopIteration: pass
打印
From generator 1
From user 2
From generator 1
From user 3
From generator 1
From user 4
...
看到控件是如何来回传递的了吗?这些是协程。它们可以用于各种很酷的事情,如异步IO和类似的。
想象一下,有一个发电机,没有发送器,这是一条单行道
========== yield ========
Generator | ------------> | User |
========== ========
但是有了send,它就变成了双向的
========== yield ========
Generator | ------------> | User |
========== <------------ ========
send
这为用户打开了一扇门,用户可以动态地定制生成器的行为和生成器对用户的响应。
itr.send(None)和next(itr)是一样的你所做的是在生成器中给出yield给出的值。
下面的例子清楚地说明了这一点,以及如何更实际地使用它。
def iterator_towards(dest=100):
value = 0
while True:
n = yield value
if n is not None:
dest = n
if dest > value:
value += 1
elif dest < value:
value -= 1
else:
return
num = iterator_towards()
for i in num:
print(i)
if i == 5:
num.send(0)
这将打印:
0
1
2
3
4
5
3
2
1
0
i == 5处的代码告诉它发送0。这不是iterator_toward中的None,所以它改变了dest的值,然后我们迭代到0。
但是请注意,在值5之后没有值4。这是因为.send(0)的性质是它被输出值为4,而不输出。
如果我们添加一个continue,我们可以重新得到相同的值。
def iterator_towards(dest=100):
value = 0
while True:
n = yield value
if n is not None:
dest = n
continue
if dest > value:
value += 1
elif dest < value:
value -= 1
else:
return
这将允许您迭代一个列表,但也动态地发送它的新目标值。
这些也让我很困惑。下面是我做的一个例子,当我试图建立一个以交替顺序(屈服,接受,屈服,接受)产生和接受信号的生成器时……
def echo_sound():
thing_to_say = '<Sound of wind on cliffs>'
while True:
thing_to_say = (yield thing_to_say)
thing_to_say = '...'.join([thing_to_say]+[thing_to_say[-6:]]*2)
yield None # This is the return value of send.
gen = echo_sound()
print 'You are lost in the wilderness, calling for help.'
print '------'
in_message = gen.next()
print 'You hear: "{}"'.format(in_message)
out_message = 'Hello!'
print 'You yell "{}"'.format(out_message)
gen.send(out_message)
print '------'
in_message = gen.next()
print 'You hear: "{}"'.format(in_message)
out_message = 'Is anybody out there?'
print 'You yell "{}"'.format(out_message)
gen.send(out_message)
print '------'
in_message = gen.next()
print 'You hear: "{}"'.format(in_message)
out_message = 'Help!'
print 'You yell "{}"'.format(out_message)
gen.send(out_message)
输出结果为:
You are lost in the wilderness, calling for help.
------
You hear: "<Sound of wind on cliffs>"
You yell "Hello!"
------
You hear: "Hello!...Hello!...Hello!"
You yell "Is anybody out there?"
------
You hear: "Is anybody out there?...there?...there?"
You yell "Help!"
send()方法控制yield表达式左边的值。
为了理解yield的不同之处以及它所代表的值,让我们首先快速刷新python代码被求值的顺序。
第6.15节评估命令
Python从左到右计算表达式。注意,在计算赋值时,右边的值比左边的值先计算。
所以表达式a = b首先求右边的值。
如下所示,a[p('left')] = p('right')首先计算右边的值。
>>> def p(side):
... print(side)
... return 0
...
>>> a[p('left')] = p('right')
right
left
>>>
>>>
>>> [p('left'), p('right')]
left
right
[0, 0]
收益率是做什么的?, yield将暂停函数的执行并返回给调用者,并在暂停之前停止的同一位置恢复执行。
死刑到底在哪里暂缓执行?你可能已经猜到了……
在yield表达式的左右之间暂停执行。因此new_val = yield old_val执行在=号处停止,并且右边的值(挂起之前,也是返回给调用者的值)可能与左边的值(恢复执行后分配的值)不同。
Yield产生两个值,一个在右边,另一个在左边。
如何控制yield表达式左边的值?通过.send()方法。
6.2.9. 产量表达式
恢复后的yield表达式的值取决于恢复执行的方法。如果使用__next__()(通常通过for或next()内置函数),则结果为None。否则,如果使用send(),则结果将是传递给该方法的值。