这是我写的一个小函数来理解send方法:
>>> def test():
... for x in xrange(10):
... res = yield
... yield res
>>> a = test()
>>> next(a)
>>> next(a)
>>> next(a)
>>> next(a)
>>> a.send(0)
Traceback (most recent call last):
<ipython-input-220-4abef3782000> in <module>()
StopIteration
>>> a = test()
>>> a.send(0)
Traceback (most recent call last):
<ipython-input-222-4abef3782000> in <module>()
TypeError: can't send non-None value to a just-started generator
>>> a.send(None)
>>> a.send(0)
0
>>> a.send(0)
>>> a.send(0)
0
>>> a.send(0)
>>> a.send(0)
0
>>> a.send(0)
为什么第一次出现错误?
>>> a.send(0)
StopIteration
为什么第一个send()需要为None?与此错误一样:
>>> a.send(0)
Traceback (most recent call last):
<ipython-input-222-4abef3782000> in <module>()
TypeError: can't send non-None value to a just-started generator
然后第一次发送启动发生器(我不知道为什么)并且我发送'0'并且它打印它但是第二次0再次没有并且恢复我发送的任何东西(0在这里)
>>> a.send(None)
>>> a.send(0)
0
>>> a.send(0)
>>> a.send(0)
0
>>> a.send(0)
>>> a.send(0)
0
的帮助不大
答案 0 :(得分:7)
第一次没有错误,在python2.7和python3.3上测试:
>>> def test():
... for x in xrange(10):
... res = yield
... yield res
...
>>> a = test()
>>> next(a)
>>> next(a)
>>> next(a)
>>> next(a)
>>> a.send(0)
>>> a.send(0)
0
>>> a.send(0)
>>> a.send(0)
0
第一次不能send()
一个值,因为生成器在你有yield语句之前没有执行,所以与值无关。
以下是pep的相关段落介绍了与生成器(http://www.python.org/dev/peps/pep-0342/)的协同例程的特性:
因为生成器迭代器开始在顶部执行 生成器的函数体,没有yield表达式可以接收 刚刚创建生成器时的值。因此, 当禁止使用非None参数调用send()时 生成器迭代器刚刚启动,如果是,则引发TypeError 这种情况发生(可能是由于某种逻辑错误)。从而, 在你可以与协程通信之前,你必须先打电话 next()或send(None)将其执行推进到第一个yield 表达
def coro():
print 'before yield'
a = yield 'the yield value'
b = yield a
print 'done!'
c=coro() # this does not execute the generator, only creates it
# If you use c.send('a value') here it could _not_ do anything with the value
# so it raises an TypeError! Remember, the generator was not executed yet,
# only created, it is like the execution is before the `print 'before yield'`
# This line could be `c.send(None)` too, the `None` needs to be explicit with
# the first use of `send()` to show that you know it is the first iteration
print next(c) # will print 'before yield' then 'the yield value' that was yield
print c.send('first value sent') # will print 'first value sent'
# will print 'done!'
# the string 'the second value sent' is sent but not used and StopIterating will be raised
print c.send('the second value sent')
print c.send('oops') # raises StopIterating
答案 1 :(得分:0)
send()
仅在生成器正在等待收益时才可以调用。由于您的生成器尚未开始执行,因此调用send()
会给您带来第一个错误。
此外,生成器中的每个收益都会消耗send()
发送的值。当第二个yield语句使用值但不使用它时,该值将被丢弃。然后等待第一个收益率的使用,该收益率确实消耗send()
中的值,并且该值被打印出来。因此,您最终需要两个send()
。
这是固定版本:
>>> def echo():
... while True:
... val = (yield)
... yield val
...
>>> g=echo()
>>> next(g) # move to 1st yield
>>> g.send(2) # execution stops at 2nd yield
2
>>> next(g) # execution stops at 1st yield
>>> g.send(3) # execution stops at 2nd yield
3
答案 2 :(得分:0)
PEP 342 New generator method: send(value)说:
调用send(None)等同于调用生成器的 next()方法。用其他任何值调用send()都是一样的,除了 发电机当前收益率表达式产生的值 会有所不同。
因为生成器迭代器从以下位置开始执行: 生成器的函数体,没有yield表达式来接收 刚刚创建生成器时的值。因此,呼叫 当生成器禁止带有非None参数的send()时 迭代器刚刚启动,如果发生这种情况,则会引发TypeError (大概是由于某种逻辑错误)。因此,在您可以 与协程通信,您必须首先调用next()或send(None) 将其执行推进到第一个yield表达式。