生成器可以理解为一种数据类型,这种数据类型自动实现了迭代器协议
(其他的数据类型需要调用自己内置的__iter__方法),所以生成器就是
可迭代对象
生成器分类及在python中的表现形式:(python有两种不同的方式提供生成器)
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回
结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便
下次从它离开的地方继续执行
def triangles():
a=[1]
while True:
yield a
a=[sum(i) for i in zip([0]+a,a+[0])]
n=0
for t in triangles():
print(t)
n=n+1
if n==10:
break
def product_baozi():
for i in range(1,10):
yield i
maibaozi=product_baozi()
print("吃包子:",next(maibaozi))
print("吃包子:",next(maibaozi))
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象
而不是一次构建一个结果列表
优点:
Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才
产生结果,而不是立即产生结果。这也是生成器的主要好处。
三元表达式
'二元' if name=="alex" else '三元'
为真执行 判断 为假执行
列表解析
egg_list=[]
for i in range(10)
egg_list.append('eggs%s'%i)
print(egg_list)
a=['eggs%s' i for i in range(10)]方括号换成圆括号就是生成器,取值内部a.__next__() next(4)
a2=('eggs %s' %i for i in range(10) if i>5)
print(a2)
print(type(a2))
print(next(a2))
print(next(a2))
总结:
1.把列表解析的[]换成()得到的就是生成器表达式
2.列表解析与生成器表达式都是一种遍历的编程方式,只不过生成器表达式更节省内存
3.生成器运行3种方式:__next__() next() send()
4.yield 3相当于return控制的是函数的返回值
5.x=yield的另一个特性,接受send传过来的值,赋值给x
import time
# def get_provice_population():
# with open(r'population.txt','r',encoding="utf-8") as f:
# for line in f:
# p=eval(line)
# yield p['population']
#
# gen=get_provice_population()
# a1=[i for i in gen]
# print(a1)
# all_population=sum(a1)
# for p in a1:
# print("%0.2f %%"%(p/all_population))
# def producer():
# ret=[]
# for i in range(10):
# ret.append('包子%s'%i)
# return ret
#
# def consumer(res):
# for index,baozi in enumerate(res):
# print('第%s个人,吃了%s'%(index,baozi))
#
# res=producer()
# consumer(res)
#单线程里并发,协程
def producer():
ret=[]
for i in range(10):
ret.append('包子%s'%i)
return ret
def consumer(name): #消费者
print('我是[%s],我准备开始吃包子了'%name)
while True:
baozi=yield
print('%s 很开心的把[%s]吃掉了'%(name,baozi))
def producer(): #生产者
c1=consumer('wupeiqi')
c2 = consumer('zhao')
c1.__next__()
c2.__next__()
for i in range(10):
time.sleep(1)
c1.send('baozi %s'%i)
c2.send('baozi %s'%i)
producer()
注意:生成器只能遍历一次