迭代器和生成器

迭代描述的就是一个重复的过程,之前学过的for和while,操作较多的就是列表,特点是:一个序列,有序,有索引。

例如:
1 l = ['a','b','c','d','e']
2 i = 0
3 while i < len(l):
4     print(l[i])
5     i+=1
6 for i in range(len(l)):
7     print(l[i])

之前用的方法都是利用有下标和索引来取需要的值,但是无法对无下标的数据取值,所以我们现在需要用到了我们今天需要用到的迭代器:

1 d = {'a':1,'b':2,'c':3}
2 d.__iter__() #等同于iter(d)
#只要被内置了__iter__方法和__next__方法的对象,就被称为可迭代对象。
1 i = d.__iter__() #   i 就是迭代器
2 print(i.__next__())
3 print(i.__next__())
这样我们就可以用迭代器来遍历字典了
1 d = {'a':1,'b':2,'c':3}
2 i = d.__iter__() #iter(d)
3 while True:
4     try:                               #抛出异常
5        print(next(i))
6     except StopIteration: ##捕捉一个叫StopIteration的异常
7         break
遍历列表
1 l = ['a','b','c','d','e']
2 i = l.__iter__()
3 while True:
4     try:                               #抛出异常
5        print(next(i))
6     except StopIteration:   #捕捉一个叫StopIteration的异常
7         break
8  
for循环
1 d = {'a':1,'b':2,'c':3}
2 for k in d:   #,python中的for循环是将 in后面的对象先调用d.__iter__()方法,并且还自动增加了try,except来操作的。
3     print()
集合
1 s = {1,2,3,4}
2 for i in s:
3     print(i)

遍历一个文件

 1 with open('a.txt','r') as f:
 2     for line in f:
 3         print(line)
 4 
 5 f = open('a.txt','r')
 6 i = f.__iter__()
 7 while True:
 8     try:
 9         print(next(i))
10     except StopIteration: 
11         break
12  
13  
14 f = open('a.txt','r')
15 f.__next__
16 f.__iter__
17 print(f)                   #
18 print(f.__iter__())  #f.__iter__()就是f本身
19 for line in f:
20     print(line)
为什么要用迭代器:
优点:
1.迭代器提供了一种不依赖于索引的取值方式,这样就可以遍历那些没有索引的可迭代对象了(字典,集合,文件)
2.迭代器于列表比较,迭代器是惰性计算的,更节省内存
缺点:
1.无法获取迭代器的长度,使用不如列表索引取值灵活;
2.迭代器是一次性的,只能往后取值,不能倒着取值
 
查看可迭代对象与迭代器对象
 1 from collections import Iterable,Iterator #导入一个模块可以使用isinstance函数来判断一个数据的类型。
 2 isinstance('ssss',str) 
 3  
 4 s = 'hello'
 5 l = [1,2,3]
 6 t = (1,2,3)
 7 d = {'a':1}
 8 set1 = {1,2,3,4}
 9 f = open('a.txt')
10  
11 #都是可迭代的
12 s.__iter__()
13 l.__iter__()
14 t.__iter__()
15 d.__iter__()
16 set1.__iter__()
17 f.__iter__()
18 print(isinstance(s,Iterable))
19  
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))

生成器:(本质其实就是迭代器)

生成器与return有何区别??
return 只能返回一次函数就彻底结束了,而yield能返回多次值
yield到底干了什么事情:
1.yield把函数变成了生成器-->迭代器
2.用return返回值能返回一次,而yield可以返回多次
3.函数在暂停以及继续下一次运行时的状态由yield保存
生成器就是一个函数,这个函数内包含有yield这个关键字
1 def test():
2    print('first') 
3    yield 1 #return 1
4 test()
5 g = test()
6 print(g)
7 
8 print(isinstance(g,Iterator))
9 print(next(g))

可以将函数作为生成器:

 1 from collections import Iterable,Iterator 
 2 def test():
 3    print('one') 
 4    yield 1 #return 1
 5    print('two') 
 6    yield 2#return 2
 7    print('three') 
 8    yield 3 #return 3
 9    print('four') 
10    yield 4#return 4
11     print('five')
12     yield 5#return 5    
13 test()
14 g = test()
15 
16  
17 res = next(g)
18 print(res)
19 res = next(g)
20 print(res)
21 res = next(g)
22 print(res)
23 res = next(g)
24 print(res)
25 res = next(g)
26 print(res)
27  
28 #或者用
29 for i in g:
30     print(i)

举例:

1 def countdown(n):
2     print('start countdown')
3     while n>0
4         yield n
5         n-=1
6     print('done')
7 g = countdown(5)

tail功能和grep功能      

将grep 也改成生成器:
 1  def eater(name):
 2     print('%s start to eat food' %name)
 3     while True:
 4         food = yield
 5         print('%s get %s to start eat' %(name,food))
 6     print('done')
 7  
 8 e = eater('钢蛋')
 9 print(e)
10 print(next(e))
11 e.send('包子') #相当于next,但是给当前的yield传一个值

 

练习一:
生成器的应用
把下述函数改成生成器的形式,执行生成器函数的到一个生成器g,然后每次g.send(url),打印页面的内容,利用g可以无限send
1 def get(url):
2         def index():
3             return urlopen(url).read()
4         return index
 1 """
 2 1.迭代器的应用
 3     文件名:a.txt,文件内容如下:
 4         apple 10 3
 5         tesla 100000 1
 6         mac 3000 2
 7         lenovo 30000 3
 8         chicken 10 3
 9 
10         实现功能:cat a.txt |grep apple
11             要求1:定义迭代器函数cat
12             要求2:定义迭代器函数grep
13             要求3:模拟管道的功能,将cat的处理结果作为grep的输入
14 """
15 # list_com = []
16 
17 def cat(file_path):
18     with open(file_path,'r',encoding='utf-8') as f_cat:
19         for line in f_cat:
20             yield line
21 
22 def grep(text,cat_result):
23     for line in cat_result:
24         if text in line:
25             yield line
26 
27 def my_com(command):
28     list_com = []
29     if '|' in command:
30         list_temp = command.split('|')
31         for i in list_temp:
32             list_com.append(i.split( ))
33         if list_com[0][0] == 'cat' and list_com[1][0]=='grep':
34             c = cat(list_com[0][1])
35             g = grep(list_com[1][1],c)
36             return g
37         else:
38             print("请您注意命令的输入格式!!")
39 
40 def main():
41     while True:
42         try:
43             try:
44                 command = input("请输入您的命令例如:(cat a.txt |grep apple):")
45                 print(next(my_com(command)))
46             except StopIteration:
47                 break
48         except TypeError:
49             print("您输入的命令有误请重新输入!!")
50             continue
51 if __name__ == '__main__':
52     main()
View Code

练习二:

迭代器的应用
文件名:a.txt,文件内容如下:
apple 10 3
tesla 100000 1
mac 3000 2
lenovo 30000 3
chicken 10 3

实现功能:cat a.txt |grep apple
要求1:定义迭代器函数cat
要求2:定义迭代器函数grep
要求3:模拟管道的功能,将cat的处理结果作为grep的输入
 1 """
 2 2.生成器的应用
 3     把下述函数改成生成器的形式,执行生成器函数的到一个生成器g,然后每次g.send(url),打印页面的内容,利用g可以无限send
 4     def get(url):
 5         def index():
 6             return urlopen(url).read()
 7         return index
 8 """
 9 from urllib.request import urlopen
10 def get(url):
11     while True:
12         def index():
13             return urlopen(url).read()
14         url = yield index()
15 
16 
17 def main():
18     while True:
19         url = input("请输入网页地址:")
20         g = get(url)
21         next(g)
22         print(g.send(url))
23 
24 if __name__ == '__main__':
25     main()
View Code

 

 

 
 

 
posted @ 2017-04-12 15:07  不老玩童萧龙  阅读(198)  评论(0编辑  收藏  举报