码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2017-04-12 16:53:14      阅读:302      评论:0      收藏:0      [点我收藏+]

标签:保存   流水线   文件   war   结束   句柄   iter   比较   这一   

一、什么是迭代器协议

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 2
10     print(five)
11     yield 5 #return 2
12 
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=0
3     while True:
4         yield n
5         n+=1
6 
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                 continue
10             else:
11                 # print(line)
12                 yield line
13 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_list
14         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_list
14         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 @init
12 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 @init
26 def opener(target):
27     打开文件,获取文件句柄
28     while True:
29         file_path=yield
30         print(车间opener开始生产产品:文件句柄)
31         time.sleep(2)
32         with open(file_path) as f:
33             target.send((file_path,f))
34 
35 @init
36 def cat(target):
37     读取文件内容
38     while True:
39         file_path,f=yield
40         print(车间cat开始生产产品:文件的一行内容)
41         time.sleep(2)
42         for line in f:
43             target.send((file_path,line))
44 
45 @init
46 def grep(pattern,target):
47     过滤一行内容中有无python
48     while True:
49         file_path,line=yield
50         print(车间grep开始生产产品:包含python这一行内容的文件路径)
51         time.sleep(0.2)
52         if pattern in line:
53             target.send(file_path)
54 
55 @init
56 def printer():
57     打印文件路径
58     while True:
59         file_path=yield
60         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基础----迭代器、生成器、协程函数

标签:保存   流水线   文件   war   结束   句柄   iter   比较   这一   

原文地址:http://www.cnblogs.com/wangyongsong/p/6694496.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!