首页 > 代码库 > python基础----迭代器、生成器、协程函数

python基础----迭代器、生成器、协程函数

一、什么是迭代器协议

1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)

2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)

3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。

 

二,为什么要用迭代器

优点:

1:迭代器提供了一种不依赖于索引的取值方式,这样就可以遍历那些没有索引的可迭代对象了(字典,集合,文件)

2:迭代器与列表比较,迭代器是惰性计算的,更节省内存

缺点:

1:无法获取迭代器的长度,使用不如列表索引取值灵活

2:一次性的,只能往后取值,不能倒着取值

 

技术分享
1 l=[a,b,c,d,e]2 i=l.__iter__()3 while True:4     try:5         print(next(i))6     except StopIteration:7         break
课堂例1
技术分享
1 d={a:1,b:2,c:3}2 d.__iter__3 for k in d:        #d.__iter__()4     print(k)
课堂例2
技术分享
 1 s={1,2,3,4} 2 for i in s: 3     print(i) 4  5 with open(a.txt,r) as f: 6     for line in f: 7         print(line) 8  9 f=open(a.txt,r)10 f.__next__11 f.__iter__12 print(f)13 print(f.__iter__())14 15 for line in f: #f.__iter__()16     print(line)17 18 i=f.__iter__()19 20 while True:21     try:                     #异常排查,与StopIteration一起用22         print(next(i))23     except StopIteration:     #异常排查,与try一起用      # except 排除24         break
课堂例3
技术分享
 1 l=[1,2,3] 2 print(len(l)) 3 i=l.__iter__() 4  5 print(next(i)) 6 print(next(i)) 7 print(next(i)) 8 print(next(i)) 9 10 11 for x in i:12     print(x)13 for x in i:14     print(x)15 for x in i:16     print(x)17 for x in i:18     print(x)
课堂例4
技术分享
 1 查看可迭代对象与迭代器对象 2  3 from collections import Iterable,Iterator 4  5 s=hello 6 l=[1,2,3] 7 t=(1,2,3) 8 d={a:1} 9 set1={1,2,3,4}10 f=open(a.txt)11 12 都是可迭代的13 s.__iter__()14 l.__iter__()15 t.__iter__()16 d.__iter__()17 set1.__iter__()18 f.__iter__()19 print(isinstance(s,Iterable))20 print(isinstance(l,Iterable))21 print(isinstance(t,Iterable))22 print(isinstance(d,Iterable))23 print(isinstance(set1,Iterable))24 print(isinstance(f,Iterable))25 26 查看是否是迭代器27 print(isinstance(s,Iterator))28 print(isinstance(l,Iterator))29 print(isinstance(t,Iterator))30 print(isinstance(d,Iterator))31 print(isinstance(set1,Iterator))32 print(isinstance(f,Iterator))
课堂例5

 

三、生成器

什么是生成器:

可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象.

from collections import Iterator   生成器就是一个函数,这个函数内包含有yield这个关键字.

生成器分类及在python中的表现形式:(Python有两种不同的方式提供生成器)

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行.

2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表.

 

为何使用生成器:

优点:

Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。

 

生成器小结:

1.是可迭代对象

2.实现了延迟计算,省内存

3.生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算省内存的好处,其余的可迭代对象可没有这点好处,记住喽!!!

 

生成器与return的区别:return只能返回一次函数就彻底结束了,而yield能返回多次值
                 
yield功能:

1.yield把函数变成生成器-->生成器本质就是迭代器

2.用return返回值能返回一次,而yield返回多次

3.函数暂停以及继续运行的状态是通过yield保存的

技术分享
 1 def test(): 2     print(one) 3     yield 1 #return 1 4     print(two) 5     yield 2 #return 2 6     print(three) 7     yield 3 #return 2 8     print(four) 9     yield 4 #return 210     print(five)11     yield 5 #return 212 13 g=test()14 print(g)15 # print(isinstance(g,Iterator))16 g.__iter__()17 g.__next__()18 19 res=next(g)20 print(res)21 22 res=next(g)23 print(res)24 25 res=next(g)26 print(res)27 28 res=next(g)29 print(res)30 31 for i in g:32     print(i)
课堂例1
技术分享课堂例2
技术分享
1 def func():2     n=03     while True:4         yield n5         n+=16 7 f=func()8 print(next(f))
课堂例3
技术分享
 1 import time 2 def tail(file_path): 3     with open(file_path,r) as f: 4         f.seek(0,2) 5         while True: 6             line=f.readline() 7             if not line: 8                 time.sleep(0.3) 9                 continue10             else:11                 # print(line)12                 yield line13 tail(/tmp/a.txt)
课堂例4

 

四、协程函数 

定义:如果在一个函数内部yield的使用方式是表达式形式的话,如x=yield,那么该函数成为协程函数

 

 #例子

1
def eater(name): 2 print(%s start to eat food %name) 3 food_list=[] 4 while True: 5 food=yield food_list 6 print(%s get %s ,to start eat %(name,food)) 7 food_list.append(food) 9 print(done)10 e=eater(钢蛋)11 print(e)12 print(next(e))13 print(e.send(包子))14 print(e.send(韭菜馅包子))15 print(e.send(大蒜包子))

 


为协程函数添加装饰器:

 1 def timmer(func): 2     def wrapper(*args,**kwargs): 3         e=func(*args,**kwargs) 4         next(e) 5         return e 6     return wrapper 7  8 @timmer        #eater=timmer(eater) 9 def eater(name):10     print(%s start to eat food %name)11     food_list=[]12     while True:13         food=yield food_list14         print(%s get %s ,to start eat %(name,food))15         food_list.append(food)16 e = eater(egon)   #wrapper(egon)17 # print(e)18 # next(e)19 print(e.send(包子))20 print(e.send(包子))   #以下每send一次都会执行一次结果21 print(e.send(包子))22 print(e.send(包子))

 

 

 补充:

 1 def init(func): 2     def wrapper(*args,**kwargs): 3         res=func(*args,**kwargs) 4         next(res) 5         return res 6     return wrapper 7  8 @init #eater=init(eater) 9 def eater(name):10     print(%s start to eat % name)11     food_list=[]12     while True:13         food = yield food_list14         print(%s eat %s % (name, food))15         food_list.append(food)16 17 e = eater(zhejiangF4) #wrapper(zhengjiangF4)18 # print(e)19 # next(e) #e.send(None)20 21 print(e.send(123))22 print(e.send(123))23 print(e.send(123))24 print(e.send(123))25 print(e.send(123))

 

五、协程函数的应用

面向过程的编程思想:流水线式的编程思想,在设计程序时,需要把整个流程设计出来

优点:   1:体系结构更加清晰

           2:简化程序的复杂度

缺点:可扩展性极其的差,所以说面向过程的应用场景是:不需要经常变化的软件,如:linux内核,httpd,git等软件

 

 旁白: 此实例包含了装饰器、迭代器、生成器、协程函数、os模块中walk命令,需要好好记住! ?????

技术分享
 1 #grep -rl ‘python‘ C:\egon 2 import os,time 3 def init(func): 4     def wrapper(*args,**kwargs): 5         res=func(*args,**kwargs) 6         next(res) 7         return res 8     return wrapper 9 10 #找到一个绝对路径,往下一个阶段发一个11 @init12 def search(target):13     找到文件的绝对路径14     while True:15         dir_name=yield #dir_name=‘C:\\egon‘16         print(车间search开始生产产品:文件的绝对路径)17         time.sleep(2)18         g = os.walk(dir_name)19         for i in g:20             # print(i)21             for j in i[-1]:22                 file_path = %s\\%s % (i[0], j)23                 target.send(file_path)24 25 @init26 def opener(target):27     打开文件,获取文件句柄28     while True:29         file_path=yield30         print(车间opener开始生产产品:文件句柄)31         time.sleep(2)32         with open(file_path) as f:33             target.send((file_path,f))34 35 @init36 def cat(target):37     读取文件内容38     while True:39         file_path,f=yield40         print(车间cat开始生产产品:文件的一行内容)41         time.sleep(2)42         for line in f:43             target.send((file_path,line))44 45 @init46 def grep(pattern,target):47     过滤一行内容中有无python48     while True:49         file_path,line=yield50         print(车间grep开始生产产品:包含python这一行内容的文件路径)51         time.sleep(0.2)52         if pattern in line:53             target.send(file_path)54 55 @init56 def printer():57     打印文件路径58     while True:59         file_path=yield60         print(车间printer开始生产产品:得到最终的产品)61         time.sleep(2)62         print(file_path)63 64 65 g=search(opener(cat(grep(python,printer()))))66 g.send(C:\\egon)67 g.send(D:\\dir1)68 g.send(E:\\dir2)
面向过程实例

 

python基础----迭代器、生成器、协程函数