1 迭代
1 #迭代器对象、可迭代对象之前提到过好多次了,其实我自己也不太明白具体的含义 2 #今天就来研究研究 3 #先来看看几种常见的用for循环遍历对象的场景吧 4 for x in [1,2,3]: 5 pass 6 7 for y in (1,2,3): 8 pass 9 10 d = {‘a‘:1,‘b‘:2} 11 for item in d.items(): 12 pass 13 14 #f = open(‘data.txt‘,‘r‘,encoding=‘UTF-8‘) 15 #for i in f: 16 # pass 17 18 #为什么这几种数据类型都可以被for循环遍历呢? 19 #因为它们都是可迭代对象,实现了迭代协议 20 #可迭代对象支持__next__()函数,能够获取到可迭代对象的下一个元素。 21 #此外还有一个全局函数next()有可以遍历可迭代对象。 22 #print(next(f)) 23 24 #由于文件对象f是可迭代对象,所有可以用for循环进行遍历 25 #for x in f.readlines(): 26 # pass 27 #f.readlines()就是将文件内容的每一行作为一个元素全部放在一个list中,如果文件太大 28 #list也会很大,就基表消耗内存了 29 #由此也可以引出可迭代对象的优势,不必把list所有元素都加载到内存中,从中 30 #取一个元素处理一个元素,如此占用的资源小,故在实际开发中,遇到要处理的数据量 31 #特别大的情况,使用可迭代对象比较好。 32 33 l = [1,2,3,4,5] 34 #print(l.__next__()) 35 36 #报错啦: 37 #Traceback (most recent call last): 38 # File "C:/Users/dddd/PycharmProjects/untitled5/test.py", line 34, in <module> 39 # print(l.__next__()) 40 #AttributeError: ‘list‘ object has no attribute ‘__next__‘ 41 42 #可见,列表并没有实现可迭代协议,之所以能用for遍历,是因为:for语句帮它多做了一步操作 43 #就是用iter()函数将其转化为迭代器对象。 44 #所以列表可以称之为可迭代对象。 45 46 #可迭代对象的本质是实现了__next__()函数,有如下两种情况 47 #一:迭代器对象(自己已经实现了__next__()) 48 #二:可迭代对象(借助for等迭代工具用iter()将其转化为迭代器对象,就能遍历了,如list就是这样) 49 50 #实际开发中,发现一个对象可以用for进行遍历,如何确认它是迭代器对象还是可迭代对象 51 #如果一个对象自己可以调用__next__(),就是迭代器对象; 52 #如果一个对象自己不可以调用__next__(),但可用for等迭代工具遍历的就是可迭代对象。 53 54 #还有一个方法区分而知,就是用iter()来判断 55 print(iter(l) is l) 56 #如果返回True,说明l自己已经实现了__next__()函数,因为iter()函数的作用就是帮助对象实现__next__()函数,所以这种是迭代器对象 57 #如果返回False,说明l自己没有实现__next__()函数,若可用for遍历,就是可迭代对象。 58 59 #可迭代对象可以用iter()函数转化为迭代器对象 60 a = [‘www.baidu.com‘,‘www.alibaba.com‘,‘www.tensen.com‘] 61 a1 = iter(a) #将a转化为迭代器对象a1 62 print(iter(a1) is a1) #返回结果为:True,说明a1是迭代器对象 63 64 #除了借助iter()帮助实现__next__(),还可以手动实现 65 s = ‘www.baidu.com‘ 66 print(iter(s) is s) #False,说明字符串不是迭代器对象 67 68 s1 = s[:] 69 s2 = iter(s1) 70 print(s2.__next__()) #w 71 72 #到这可能会问了,我为什么要费劲巴拉转换呢,直接用for来遍历不就好了吗? 73 #上边也提到了,将可迭代对象转化为迭代器对象,可以在数据量比较大的情况下节省内存开支 74 #这一点在实际开发中比较重要,毕竟计算机的内存是有限的。 75 76 l = [1,2,3,4,5,6,7] 77 res = [] 78 for x in l: 79 res.append(x**2) 80 81 #如果l很大,这个资源消耗就很大了。 82 83 #所以下边尝试手工把l这个可迭代对象转化为迭代器对象 84 ll = iter(l) 85 res1 = [] 86 while True: 87 try: 88 x = next(ll) #这样就做到处理哪个元素就把哪个元素加载到内存中 89 res1.append(x**2) 90 except StopIteration: 91 break 92 93 print(res1) #[1, 4, 9, 16, 25, 36, 49] 94 95 96 #据说啊,列表之所以没有自动实现__next__(),是因为雷彪中还可以存放其他的数据结构,比如再嵌套一个列表、元组、字典、函数名等。
可迭代对象实现了可迭代协议
可迭代对象包括list、tuple、file、generator等
迭代工具:上下文、for、map、comprehension、推导,应用在可迭代对象上,将可迭代对象作为参数传递给iter()
返回迭代器对象,然后迭代工具调用next()处理可迭代对象。
2 推导
1 #说起效率,最高的还是推导,因为在解释器中是使用c语言实现的 2 l = [1,2,3,4,5] 3 res1 = [x**2 for x in l] 4 print(res1) #[1, 4, 9, 16, 25, 36, 49] 5 6 #in l 表示要遍历的范围 7 #for 后的 x 用于存放每次循环获得的临时变量 8 #x**2 这部分表示获取的元素如何处理 9 #推导返回的数据类型由外侧的括号类型决定,如[]表示返回列表,()表示返回元组。 10 11 #新需求,给l中的每个元素都加10 12 res2 = [(x + 10) for x in l] 13 print(res2) #[11, 12, 13, 14, 15] 14 15 url = [‘www.xxx.com‘,‘www.yyy.cn‘] 16 #只取url列表中以‘.com‘结尾的元素 17 res3 = [x for x in url if x.endswith(‘.com‘)] 18 print(res3) #[‘www.xxx.com‘] 19 20 #还记得range类型吗,是可迭代对象,可以手动转化为迭代器对象 21 r = range(0,5) 22 i = iter(r) 23 print(i) #<range_iterator object at 0x0000000000E8AF30> 24 print(i.__next__()) #0 25 print(next(i)) #1 26 27 #还记得上节课学习的函数工具吗? 28 #列表推导与map() 29 score = [66,77,47,38,88,99] 30 #需求:给每门成绩加2分 31 #实现方法一:推导 32 scores = [ (x + 2) for x in score] 33 34 #实现方法二:用map() 35 m = map(lambda x:x+2,score) 36 scoress = list(m) 37 38 #列表推导与filter() 39 #需求:筛选出及格的成绩 40 #实现方法一:推导 41 score1 = [x for x in score if x >= 60 ] 42 43 #实现方法二:filter() 44 def fun(x): 45 if x >= 60: 46 return True 47 48 f = filter(fun,score) 49 score2 = list(f)