函数中包含yield关键字,该函数不再是普通函数,而是一个生成器(generator),首次调用该函数即创建一个生成器。
最简单的创建生成器的方式是把列表推导式的[]换成(),其次则是函数中带yield关键字。生成器是Python中一边循环一边计算的机制,无需创建完整的List。
for i in range(10000):
print(i)
上述两行代码中列表range(10000)中的数据都存储在内存中,如果数据庞大则非常消耗内存。而使用生成器可以节约大量内容空间。
带yield关键字的函数示例:
1、创建带yield关键字的函数
def foo():
print('starting...')
while True:
res=yield 4#yield的功能与return相似,相当于返回4
print('res:',res)
2、创建生成器
g=foo()#首次调用即得到生成器g,此处函数并未真正执行
3、生成器迭代
next()函数和send()函数均可让生成器继续往下走一步,遇到关键字yield即停,因为yield相当于return。send()函数相比于next()函数能传入一个值,这个值可以作为yield表达式的结果。
next(g)#函数开始正式执行,到yield行停止。这里到yield 4程序即停止,并未完成赋值操作
输出:
starting…
4
next(g)#从yield的下一条语句继续向下执行,仍然到下一个循环的yield行停止。因为上一步并未完成赋值操作,从print('res:',res)语句开始执行,res为None
输出:
res: None
4
g.send(7)#send()函数向yield行传入值:7,同样从yield的下一条语句print('res:',res)开始执行,因为已经传入值7,所以res的结果为7
输出:
res: 7
4
通常做法中,基本上不会采用next()来获取返回值,而是直接使用for循环来获取返回值,完成生成器迭代。因为for循环本身的原理就是通过类似于next()函数完成迭代。
for循环生成器迭代示例:
def foo(num):
print('starting...')
while num<10:
num=num+1
yield num
for i in foo(0):# foo(0)即创建生成器,for循环next迭代机制使得生成器开始迭代执行,直到捕获一个异常,迭代结束
print(i)
输出:
starting…
1
2
3
4
5
6
7
8
9
10