6.10 迭代器
1、什么是迭代:指的是一个重复的过程,每一次重复称为一次迭代,并且每一次重复的结果是下一次重复的初始值
l=['a','b','c'] count=0 while count < len(l): #只是单纯地重复,因而不是迭代 print(l[count]) count+=1
2 为什么要有迭代器?
对于序列类型:str,list,tuple,可以依赖索引来迭代取值,
但是对于dict,set,文件,python必须为我们提供一种不依赖于索引的迭代取值的方式--》迭代器
3、 可迭代的对象(下列都是):obj.__iter__
name='egon' l=[1,2,3] t=(1,2,3) d={'name':'egon','age':18,'sex':'male'} s={'a','b','c'} f=open('a.txt','w',encoding='utf-8') name.__iter__ l.__iter__ t.__iter__ d.__iter__ s.__iter__ f.__iter__
4、 迭代器对象(文件是):obj.__iter__,obj.__next__
f=open('a.txt','w',encoding='utf-8')
f.__iter__
f.__next__
5、总结:
1 可迭代对象不一定是迭代器对象
2 迭代器对象一定是可迭代的对象
3 调用obj.__iter__()方法,得到的是迭代器对象,对于迭代器对象,执行__iter__得到的仍然是它本身)
d={'name':'egon','age':18,'sex':'male'} d_iter=d.__iter__() #得到迭代器对象 f=open('a.txt','w',encoding='utf-8') f_iter=f.__iter__().__iter__().__iter__().__iter__() #迭代器对象得到的仍然是它本身 print(f_iter is f) #True #字典 d={'name':'egon','age':18,'sex':'male'} #可迭代对象 d_iter=d.__iter__() #迭代器对象 print(d_iter.__next__()) print(d_iter.__next__()) print(d_iter.__next__()) print(d_iter.__next__()) #迭代器d_iter没有值了,就会抛出异常StopIteration #文件 f=open('a.txt','r',encoding='utf-8') print(f.__next__()) print(f.__next__()) print(f.__next__()) print(f.__next__()) f.close() #列表 l=['a','b','c'] l_iter=l.__iter__() print(l_iter.__next__()) print(l_iter.__next__()) print(l_iter.__next__()) print(l_iter.__next__()) #处理异常(可用for循环,for循环自带处理异常) d={'name':'egon','age':18,'sex':'male'} d_iter=iter(d) #d_iter=d.__iter__() while True: try: print(next(d_iter)) #print(d_iter.__next__()) except StopIteration: #捕获异常 break print('=>>>')
6、for循环详解:
1、调用in后的obj_iter=obj.__iter__(),得到一个迭代器对象iter_dic
2、k=obj_iter.__next__()
3、重复过程2,直到捕捉到异常StopIteration,结束循环
d={'name':'egon','age':18,'sex':'male'} for k in d: print(k)
7、总结迭代器的优缺点:
优点:
1、提供一种统一的、不依赖于索引的取值方式,为for循环的实现提供了依据
2、迭代器同一时间在内存中只有一个值——》更节省内存,
缺点:
1、只能往后取,并且是一次性的
2、不能统计值的个数,即长度
6.11 生成器
6.11.1 生成器
1、什么是生成器:只要在函数体内出现yield关键字,那么再执行函数就不会执行函数代码,会得到一个结果,该结果就是生成器
def func(): print('=====>1') yield 1 print('=====>2') yield 2 print('=====>3') yield 3
2、生成器就是迭代器
g=func() #g是生成器 res1=next(g) print(res1) res2=next(g) print(res2) res3=next(g) print(res3)
3、yield的功能:
1、yield为我们提供了一种自定义迭代器对象的方法
2、yield与return的区别
1)yield可以返回多次值
2)函数暂停与再继续的状态是由yield帮我们保存的
#自己编写rang()函数 def my_range(start,stop,step=1): while start < stop: yield start #start=1 start+=step #start=3 g=my_range(1,5,2) print(g) #print(next(g)) #print(next(g)) for i in my_range(1,5,2): print(i)
4、小练习::tail -f access.log | grep '404'
import time def tail(filepath): with open(filepath,'rb') as f: f.seek(0,2) while True: line=f.readline() if line: yield line else: time.sleep(0.05) def grep(lines,pattern): for line in lines: line=line.decode('utf-8') if pattern in line: yield line lines=grep(tail('access.log'),'404') for line in lines: print(line)
6.11.2 yield表达式形式的用法
def eater(name): print('%s ready to eat' %name) food_list=[] while True: food=yield food_list #food=yield='一盆骨头' food_list.append(food) print('%s start to eat %s' %(name,food)) e=eater('alex') #首先初始化: print(e.send(None)) # next(e) #然后e.send:1 从暂停的位置将值传给yield 2、与next一样 print(e.send('一桶泔水')) print(e.send('一盆骨头'))
6.12 面向过程编程
1、首先强调:面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序
2、定义
面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么
基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式
3、优点:复杂的问题流程化,进而简单化
4、缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身
5、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd
6、举例
流水线1:
用户输入用户名、密码--->用户验证--->欢迎界面
流水线2:
用户输入sql--->sql解析--->执行功能
grep -rl 'python' /etc
# 第一步:拿到一个文件夹下所有的文件的绝对路径 import os def init(func): def inner(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return inner @init def search(target): # r'D:\video\python20期\day4\a' while True: filepath = yield g = os.walk(filepath) for pardir, _, files in g: for file in files: abs_path = r'%s\%s' % (pardir, file) #把abs_path传给下一个阶段 target.send(abs_path) # 第二步:打开文件拿到文件对象f @init def opener(target): while True: abs_path = yield with open(abs_path,'rb') as f: #把(abs_path,f)传给下一个阶段 target.send((abs_path,f)) #第三步:读取f的每一行内容 @init def cat(target): while True: abs_path,f=yield for line in f: #把(abs_path,line)传给下一个阶段 res=target.send((abs_path,line)) #满足某种条件,break掉for循环 if res: break #第四步:判断'python' in line @init def grep(target,pattern): pattern = pattern.encode('utf-8') res=False while True: abs_path,line=yield res res=False if pattern in line: #把abs_path传给下一个阶段 res=True target.send(abs_path) #第五步:打印文件路径 @init def printer(): while True: abs_path=yield print('<%s>' %abs_path) g=search(opener(cat(grep(printer(),'python')))) #'python' in b'xxxxx' g.send(r'D:\video\python20期\day4\a')
面向过程编程:核心是过程二字,过程指的就是解决问题的步骤,即先干什么后干什么。。。。
基于该思路编写程序就好比设计一条流水线,是一种机械式的思维方式
优点:复杂的问题流程化、进而简单化
缺点:可扩展性差