生成器
本文援引自:http://www.cnblogs.com/smallmars/p/6939519.html
1.定义
生成器(generator)是一个特殊的迭代器,它的实现更简单优雅,yield是生成器实现__next__()方法的关键。它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回。
也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。
yield的功能:
1.相当于为函数封装好__iter__和__next__
2.return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行
例:
def counter(n):
print('start...')
i=0
while i < n:
yield i
i+=1
print('end...')
g=counter(5)
print(g)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
# print(next(g)) #会报错
输出
start... 0 1 2 3 4
2.生成器函数
- 生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行;
普通函数return返回
def lay_eggs(num):
egg_list=[]
for egg in range(num):
egg_list.append('蛋%s' %egg)
return egg_list
yikuangdan=lay_eggs(10) #我们拿到的是蛋
print(yikuangdan)
输出
['蛋0', '蛋1', '蛋2', '蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']
迭代器函数
def lay_eggs(num):
for egg in range(num):
res='蛋%s' %egg
yield res #生成器关键语法
print('下完一个蛋')
laomuji=lay_eggs(10) #我们拿到的是一只母鸡
print(laomuji)
print(laomuji.__next__()) #迭代 蛋0
print(laomuji.__next__()) #蛋1
print(laomuji.__next__()) #蛋2
egg_l=list(laomuji)
print(egg_l)
输出
蛋0 下完一个蛋 蛋1 下完一个蛋 蛋2 下完一个蛋 下完一个蛋 下完一个蛋 下完一个蛋 下完一个蛋 下完一个蛋 下完一个蛋 下完一个蛋 ['蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']
3.生成器表达式
- 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表;
-
food=yield food_list
#g.send('food1'),先把food1传给yield,由yield赋值给food,然后返回给food_list,然后再往下执行,直到再次碰到yield,然后把yield后的返回值返回给food_list
例
注意:开始生成器不能send非空值
def eater(name): #协程函数
print('%s ready to eat' %name)
food_list=[]
while True:
food=yield food_list #装饰器表达式
food_list.append(food)
print('%s start to eat %s' %(name,food))
g=eater('hexin')
print(g) #生成器
print(g.send('food1')) #传值
输出
Traceback (most recent call last):
<generator object eater at 0x1049030f8> #生成器对象
File "/Users/hexin/PycharmProjects/py3/day5/2.py", line 71, in <module>
print(g.send('food1'))
TypeError: can't send non-None value to a just-started generator #开始生成器不能send非空值
- 初始化后
def eater(name): #协程函数
print('%s ready to eat' %name)
food_list=[]
while True:
food=yield food_list #装饰器表达式
food_list.append(food)
print('%s start to eat %s' %(name,food))
g=eater('hexin')
print(g) #生成器
next(g) #等同于 g.send(None),初始化
print(g.send('food1'))
输出
<generator object eater at 0x107cde258> hexin ready to eat hexin start to eat food1 ['food1']
- 为了防止忘记初始化,可利用装饰器进行初始化,如下
def deco(func): #初始化函数
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
next(res) #等同于 g.send(None),初始化
return res
return wrapper
@deco #用初始化函数装饰器,调用初始化函数
def eater(name): #协程函数
print('%s ready to eat' %name)
food_list=[]
while True:
food=yield food_list #装饰器表达式
food_list.append(food)
print('%s start to eat %s' %(name,food))
g=eater('hexin')
# print(g) #生成器
# next(g) #等同于 g.send(None),初始化
print(g.send('food1'))
print(g.send('food2'))
print(g.send('food3'))
输出
hexin ready to eat hexin start to eat food1 ['food1'] hexin start to eat food2 ['food1', 'food2'] hexin start to eat food3 ['food1', 'food2', 'food3']


浙公网安备 33010602011771号