python中的迭代器和生成器
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
本篇博客主要介绍的知识点如下:
1>.初识迭代器;
2>.可迭代对象和迭代器对象的区别;
3>.初识生成器;
4>.生成器的案例展示;
一.初识迭代器
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 9 PersonalInformation = { 10 "Name":"yinzhengjie", 11 "Age":18, 12 "Habby":"Game", 13 "ProgramingLanguage":"Golang and Python" 14 } 15 16 17 18 # iterator = PersonalInformation.__iter__() #这里的iterator就是一个迭代器。 19 # 20 # print(iterator.__next__()) 21 # print(iterator.__next__()) 22 # print(iterator.__next__()) 23 # print(iterator.__next__()) 24 # print(iterator.__next__()) #如果把值取完之后,会抛出异常“StopIteration”提示用户! 25 26 27 obj = PersonalInformation.__iter__() 28 29 while True: 30 try: 31 i = obj.__next__() 32 print(i) 33 except StopIteration: 34 break 35 36 37 38 for i in PersonalInformation: 39 print(i) 40 41 42 43 """ 44 一.迭代的特点: 45 1>.重复; 46 2>.下一次重复是基于上一次的结果; 47 48 二.什么是迭代器: 49 Python为了提供一种不依赖索引的迭代方式,python会为一些对象内置"__iter__"方法,也就是说只要一个对象有 50 “__iter__”方法,"obj.__iter__"称为可迭代的对象。“obj.__iter__()”得到的结过就是迭代器。得到的迭代器即 51 有“.__iter__”方法,又会多出来一个“__next__”方法。“obj.__iter__()__next__”可以进行取值操作。 52 53 三.迭代器优点 54 1>.提供了一种不依赖索引的取值方式; 55 2>.惰性计算,可以节省内存(迭代器每次只能逐个取值,比如取文件的每一行); 56 57 四.迭代器缺点 58 1>.取值不如按照索引取值方便; 59 2>.取值是一次性的,只能往后取值,取值的顺序是不可逆的; 60 3>.无法获取迭代器的长度,直到抛出“StopIteration”异常才会结束迭代。 61 62 温馨提示:Python中的for循环就是采用了迭代器的原理,没有抛出“StopIteration”提示信息是因为其源码里做了异常处理。 63 """ 64 65 66 67 68 #以上代码执行结果如下: 69 Name 70 Age 71 Habby 72 ProgramingLanguage 73 Name 74 Age 75 Habby 76 ProgramingLanguage
二.可迭代对象和迭代器对象的区别
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 from collections import Iterable,Iterator #注意,Iterable是判断对象是否是可迭代对象,而Iterator是用来判断是判断对象是否第迭代器对象。 8 9 string_1 = "yinzhengjie" 10 list_1 = [1,2] 11 tuple_1 = (300,400,) 12 dict_1 = {"Name":"yinzhengjie","Age":"18"} 13 set_1 = (5,6) 14 file_1 = open("a.txt","w") 15 file_1.close() 16 17 #判断是否是可迭代对象 18 print("%s是否是可迭代对象:%s"%(string_1,isinstance(string_1,Iterable))) 19 print("%s是否是可迭代对象:%s"%(list_1,isinstance(list_1,Iterable))) 20 print("%s是否是可迭代对象:%s"%(tuple_1,isinstance(tuple_1,Iterable))) 21 print("%s是否是可迭代对象:%s"%(dict_1,isinstance(dict_1,Iterable))) 22 print("%s是否是可迭代对象:%s"%(set_1,isinstance(set_1,Iterable))) 23 print("%s是否是可迭代对象:%s"%(file_1,isinstance(file_1,Iterable))) 24 25 print("*"*50,"我是分割线","*"*50) 26 #判断是否是迭代器。 27 print("%s是迭代器吗:%s"%(string_1,isinstance(string_1,Iterator))) 28 print("%s是迭代器吗:%s"%(list_1,isinstance(list_1,Iterator))) 29 print("%s是迭代器吗:%s"%(tuple_1,isinstance(tuple_1,Iterator))) 30 print("%s是迭代器吗:%s"%(dict_1,isinstance(dict_1,Iterator))) 31 print("%s是迭代器吗:%s"%(set_1,isinstance(set_1,Iterator))) 32 print("%s是迭代器吗:%s"%(file_1,isinstance(file_1,Iterator))) 33 34 35 #for循环中的小提示: 36 # with open("a.txt",encoding="utf-8")as f: 37 # for line in f:#此处的f是一个可迭代对象,并不能判断出f就是迭代器哟! 38 # print(line) 39 40 41 42 43 44 45 46 #以上代码执行结果如下: 47 yinzhengjie是否是可迭代对象:True 48 [1, 2]是否是可迭代对象:True 49 (300, 400)是否是可迭代对象:True 50 {'Name': 'yinzhengjie', 'Age': '18'}是否是可迭代对象:True 51 (5, 6)是否是可迭代对象:True 52 <_io.TextIOWrapper name='a.txt' mode='w' encoding='cp936'>是否是可迭代对象:True 53 ************************************************** 我是分割线 ************************************************** 54 yinzhengjie是迭代器吗:False 55 [1, 2]是迭代器吗:False 56 (300, 400)是迭代器吗:False 57 {'Name': 'yinzhengjie', 'Age': '18'}是迭代器吗:False 58 (5, 6)是迭代器吗:False 59 <_io.TextIOWrapper name='a.txt' mode='w' encoding='cp936'>是迭代器吗:True
三.初识生成器
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 from collections import Iterator 8 ''' 9 一.什么是生成器: 10 函数体内包含有“yield”关键字,该函数执行的结果就是生成器。生成器就是迭代器,即生成器也拥有“__iter__”方法和 11 “__next__”方法。 12 13 二.yield的功能 14 1>.与普通函数中的return功能类似,都可以返回值,但不一样的地方在yield可以返回多次值,而return只能返回一次值; 15 2>.为函数封装号了“__iter__”方法和“__next__”方法,把函数的执行结果做成了迭代器; 16 3>.遵循迭代器的取值方式“obj.__next__()”,触发的函数的执行,函数暂停与再继续的状态都是由yield保存起来的; 17 ''' 18 19 def foo(): 20 print("Form First") 21 yield 100 22 print("Form Second") 23 yield 200 24 print("Form Third") 25 yield 300 26 print("end") 27 28 g = foo() #这里的变量g就是一个生成器。 29 print(isinstance(g,Iterator)) #判断生成器是否迭代器。 30 31 res1 = g.__next__() 32 print(res1) 33 res2 = g.__next__() 34 print(res2) 35 res3 = g.__next__() 36 print(res3) 37 # res4 = g.__next__() #当迭代完毕之后,也会抛出StopIteration异常哟! 38 # print(res4) 39 40 41 42 43 44 #以上代码执行结果如下: 45 True 46 Form First 47 100 48 Form Second 49 200 50 Form Third 51 300
四.生成器的案例展示
1.生成器计数功能案例
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 def Counts(num): 9 print("Start Count!") 10 while num > 100: 11 yield num 12 num -= 100 13 print("Stop Count!") 14 15 16 g = Counts(1000) 17 18 while True: 19 try: 20 print(g.__next__()) 21 except StopIteration: 22 break 23 24 # for i in g: #由于生成器满足迭代器的所有优点,因此跌大器也是不可逆的,上面的While将生成器的值取完后是不可逆的! 25 # print(i) 26 27 28 # print(Counts(500).__next__()) #注意,改行和以下两行的生成器其实并不是同一个生成器! 29 # print(Counts(500).__next__()) 30 # print(Counts(500).__next__()) 31 32 print(Counts(300),Counts(300),Counts(300)) #虽然他们三个长得一样,但是确实三个不同的生成器,他们的内存IP也是不一样的哟! 33 34 35 36 37 #以上代码执行结果如下: 38 Start Count! 39 1000 40 900 41 800 42 700 43 600 44 500 45 400 46 300 47 200 48 Stop Count! 49 <generator object Counts at 0x02AE90F0> <generator object Counts at 0x02AE9120> <generator object Counts at 0x02AE9150>
2.用生成器模拟Linux的tail功能
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import time 8 9 def tail(filepath,encoding="utf-8"): 10 with open(filepath,encoding=encoding)as f: 11 f.seek(0,2) #注意,这个2表示光标从文件的末尾开始计数,前面的0表示从末尾一行往前移动0个光标位置,换句话说,切换到文件末尾。 12 while True: 13 line = f.readline() 14 if line: 15 # print(line,end="") #end=""表示把一行的换行符去掉 16 yield line 17 else: 18 time.sleep(0.1) 19 20 def grep(lines,MatchingString): 21 for line in lines: 22 if MatchingString in line: 23 yield line 24 25 26 27 g1 = tail("a.txt") 28 g2 = grep(g1,"yinzhengjie") 29 g3 = grep(g2,"http://www.cnblogs.com/yinzhengjie/p/8467930.html") 30 31 32 for i in g3: 33 print(i)