迭代器和生成器
迭代描述的就是一个重复的过程,之前学过的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()
练习二:
迭代器的应用
文件名: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()