Py迭代和迭代器,生成器,生产者和消费者模型
迭代器iter
1.迭代的含义:
每次生成的结果依赖于上一次。问路,先问第一个人,第
一个人不知道他就说第二个人知道,然后去找第二个人。第二个人不知道
就说第三个人知道,然后去找第三个人
一个人不知道他就说第二个人知道,然后去找第二个人。第二个人不知道
就说第三个人知道,然后去找第三个人
2.递归的含义:
问路,先问第一个人,不知道就第一个人问第二个人,还
不知道就第二个人问第三个,还不知道就第三个人问第四个。如果第四
个知道了就告诉第三个,第三个告诉第二个,一直反复
然后告诉给原来问路的那个人
一个方法一代接一代下去,也有可能会出现异常,终止迭代。(只能接着往下
走没有后退的路)
他们没有.next的附加方法,但是在for调用他们的时候,调用了他们内部的__iter__
方法,把他们都变成了可迭代对象。
不知道就第二个人问第三个,还不知道就第三个人问第四个。如果第四
个知道了就告诉第三个,第三个告诉第二个,一直反复
然后告诉给原来问路的那个人
3.迭代器协议:
对象必须要提供一个next的下一步的方法。就像生孩子传宗接代一样,要按着一个方法一代接一代下去,也有可能会出现异常,终止迭代。(只能接着往下
走没有后退的路)
4.可迭代对象:实现了迭代器协议的对象。
5.for循环只能遍历可迭代对象。
(字符串,列表,元组,字典,集合,文件对象)这些其实不是可迭代对象,因为他们没有.next的附加方法,但是在for调用他们的时候,调用了他们内部的__iter__
方法,把他们都变成了可迭代对象。
x='hello' #变字符串的成可迭代 diedai = x.__iter__() print(diedai.__next__()) #本句也可以改成print(next(diedai)) print(diedai.__next__()) dic={'a':1,'b':2} #变字典的成可迭代 died=dic.__iter__() print(died.__next__()) print(died.__next__()) died1=dic.values().__iter__() print(died1.__next__()) print(died1.__next__())
生成器
1.生成器定义:
生成器是一种数据类型,这种数据类型自动实现了迭代器协议
,不用执行iter方法,它本身就是可迭代对象。它可以直接用.next()。生成器很
节省内存,next()显示下一个之后上一个会被删掉。
,不用执行iter方法,它本身就是可迭代对象。它可以直接用.next()。生成器很
节省内存,next()显示下一个之后上一个会被删掉。
2.生成器在python内有两种表达方式
第一种:
生成器函数,在函数内用yield语句而不是return可以将函数变成生成
器函数。
器函数。
def test(): yield 1 yield 'sb' yield 'nt' g=test() print(g.__next__()) print(g.__next__())
第二种:生成器表达式
首先需要了解三元表达式
#三元表达式,先看中间再看左边最后右边
name='alex' res='sb' if name == 'alex' else 'shuai' #本句为3元表达式 #如果名字是alex就把sb赋值给res,if的结果写在前面,而else的结果帅写后面 print(res)
还需要了解一下列表解析
#列表解析 egglist=[] #建立一个空的列表 for i in range(10): egglist.append('鸡蛋%s' %i) print(egglist) #接下来用列表解析优化 l=['鸡蛋%s' %i for i in range(10)] #用列表解析和三元表达式弄出标签大于5的鸡蛋 l1=['鸡蛋%s' %i for i in range(10) if i>5] print(l) print(l1)
接下来来说生成器表达式
生成器表达式就是列表解析把[]改成()
laomuji=('鸡蛋%s' %i for i in range(10)) #此时laomuji就已经是生成器表达式,可迭代对象 print(laomuji.__next__()) print(laomuji.__next__()) print(laomuji.__next__()) print(laomuji.__next__())
实例:现做现卖包子
#使用__next__()是走到yield的位置就跳出,下一次next从当前跳出位置开始 def product_baozi(): for i in range(1,100): #循环做包子 print('正在生产包子') yield '第 %s 个包子' %i #第一次调用next来到这跳出,下一次next调用从这开始 print('开始卖包子') pro_g=product_baozi() print(pro_g.__next__()) print(pro_g.__next__()) print(pro_g.__next__())
实例2:统计出字典中的每个地方的人口占据的人口比例
人口.txt内的内容
{'name':'北京','population':'10'}
{'name':'山东','population':'1000'}
{'name':'山西','population':'30010'}
{'name':'河北','population':'15200'}
{'name':'台湾','population':'750'}
{'name':'北京','population':'10'}
{'name':'山东','population':'1000'}
{'name':'山西','population':'30010'}
{'name':'河北','population':'15200'}
{'name':'台湾','population':'750'}
程序:
#采用readline函数进行实现 算出人口比例 f=open('人口','r',encoding='utf8') ret1=[] ret=[] i=0 i1=0 while i<5: ret=eval(f.readline()) ret1.append(int(ret['population'])) i=i+1 qiuhe=sum(ret1) print(qiuhe) while i1<5: print('%s %%' %(ret1[i1]/qiuhe)) i1=i1+1
#采用生成器来做
def getpopulation(): f=open('人口','r',encoding='utf8') for i in f: yield i g=getpopulation() qiuhe=0 qiuhe=sum(int(eval(i1)['population']) for i1 in g) #先看右边生成器迭代取每列,然后 print(qiuhe) #看左边把每列转换字符串,取人口,变数字型 g=getpopulation() for p in g: pnumber=int(eval(p)['population']) print(pnumber/qiuhe)
生产消费者模型:
两者是并发运行的,一个生产然后跳到另一个消费,如此循环
采用生成器yield可以达到这个效果
采用生成器yield可以达到这个效果
1.首先需要了解启动生成器的第三种方法
之前只学过__next__和next()两种方法,还有一种方法用send
# def test(): # print('开始了') # yield 1 # print('第一次') # yield 2 # t=test() # t.send(None) #用none的话和t.__next__()没区别 #send的优势是可以将一个值赋值给yield的那一行位置的形参 def test1(): print('开始了') shit=yield 1 print('第一次',shit) fuck=yield 2 print('第2次') print(fuck) yield 3 t=test1() t.send(None) #光标运行至yield1 res2=t.send('m870') #此时m870将传递给yield1然后传给shit,而且光标将运行到yield2 t.send('m8') #当前光标在yield2,传m8给yeild2给fuck,而且光标运行到yield3 print('\n') print(res2) #而且可以通过res2来接收yield的ruturn值
2.接下来来看并发的生产消费模型
import time def consumer(name): print('我是%s,我准备开始吃包子' %name) while 1: time.sleep(1) print('包子生产好了') baozi=yield print('我是%s,我开始吃%s包子' %(name,baozi)) def producer(name,eattime): c1=consumer(name) #启动生成器 c1.__next__() #光标移动至yield for i in range(eattime): time.sleep(1) c1.send('第%s个屎馅' %i) #将屎馅传给yield传给baozi,因为while一直循环,光标到下一次yeild producer('沙比',3)

浙公网安备 33010602011771号