yield 的 StopIteration 请帮我解释一下

def tt():
    x = yield
    print('x=', x)
    pass

gen = tt()
gen.send(None)            
gen.send(11)     
print('--------')
gen.close()

我的理解是,send给生成器发送数据11--->函数tt()里面执行完毕--->又回到send那里,这时候不是应该继续正常执行send后面的代码吗,send后面又没有再次调用生成器,为什么这个时候会抛出StopIteration这个异常呢? 难道send方法调用两次??

阅读 10.2k
3 个回答
def tt():
    x = yield
    print('x=', x)
    return 'EXPECTED ERROR'


gen = tt()  # 获取生成器对象
print(gen)  # <generator object tt at 0x00000235C79EDF10>
gen.send(None)  # 等价于next(gen), 启动语句找到第一个yield
recv = gen.send(11)  # yield 返回None,并继续运行到下一个yield
print(recv)
#当生成器内部执行到return语句时(或者隐式的 return None),自动抛出StopIteration异常,return的值将作为异常的解释
print('--------')
gen.close()  

过程少了一步:send给生成器发送数据11--->函数tt()里面执行完毕--->找下一个yield语句--->又回到send那里,因为这里它找下一个yield语句找不到,所以就会报StopIteration异常。

第一个send(None)走到第一个yield这里,因为生成器刚启动的第一次是不执行的,而只是悬空等待。第二次send(11),才开始执行赋值语句x = yield,但执行完之后,它又会寻觅下一个yield进行等待,因为找不到,所以就报错。

只需要把pass改成yield就可以了:

def tt():
    x = yield
    print('x=', x)
    yield

gen = tt()
gen.send(None)            
gen.send(11)     
print('--------')
gen.close()

实际上yield这个词有阻止和等待的意思,你看一看美国的路牌就知道了:

clipboard.png

在几乎所有小路上大路的地方,都立有这样的标志,类似于中国的缓行避让的意思。所以在这里,一看见yield,马上就停止,大概就是这个意思。

很简单,函数执行完 当然抛出 异常

推荐问题
宣传栏