迭代器
- 列表解析与for循环
- iter与next
- map、zip与filter迭代器
- ord函数
- 矩阵与列表解析
- 生成器(generator)
- send与next
列表解析与for循环:
for循环用来遍历迭代对象中的每一个项,会在每次迭代中调用该对象的__next__方法,而且会捕捉StopIteration异常,从而决定何时停止循环。
列表解析和for循环都是迭代工具,列表解析是执行常见for循环的简明并且高效的方案:对可迭代对象内所有元素应用一个表达式,并且收集结果。可以把列表解析转换成for循环,列表解析的部分语法看起来就像是for循环的首行。
#for循环遍历并且修改列表 >>> List = [1,2,3,4,5] >>> for i in range(len(List)): List[i] += 10 >>> List [11, 12, 13, 14, 15] #列表解析修改,跟for循环相比,列表解析运用代码更少却更快捷 >>> L = [i + 10 for i in List] >>> L [21, 22, 23, 24, 25]
iter和next:
#next方法 >>> i = open('new.txt') >>> next(i) '(1)未来10年,经济成长依然是政?权合法性的默认理由和遗训。朝野将继续一致不顾廉耻的赚?钱。\n' >>> i.__next__() '(2)金融继续有限度推进开放,但节奏会比WTO设计的慢,金融问题,留待下节讨论。\n' #使用iter迭代 >>> L = [1,2,3,4,5] #列表此时不能使用next方法,会曝TypeError异常 >>> I = iter(L) #将列表封装进iter >>> next(I) 1 >>> next(I 2 ...... >>> I.__next__() 4 >>> I.__next__() 5 #迭代完毕后如果继续运行,将会弹出StopIteration异常
map、zip、filter迭代器
#map方法 >>> a=(1,2,3) >>> A = map(abs,a) >>> next(A) 1 >>> A.__next__() 2 #filter方法 >>> list(filter(bool,['hello','','world','!','over'])) ['hello', 'world', '!', 'over']
ord函数
#python的ord函数会返回一个ASCII整数编码 >>> test = 'kola' >>> List = [] >>> for x in test: #通过for循环遍历字符串 List.append(ord(x)) #通过append,将ord传入列表中 >>> List [107, 111, 108, 97]
矩阵列表解析
#建立一个列表矩阵 >> M=[[1,2,3],[4,5,6],[7,8,9],[0,0,0]] >>> M [[1, 2, 3], [4, 5, 6], [7, 8, 9], [0, 0, 0]] >>> [row[1] for row in M] [2, 5, 8, 0] >>> [M[row][1] for row in (1,2,3)] [5, 8, 0] >>> [M[i][i]for i in range(3)] [1, 5, 9] #通过列表解析来混合多个矩阵 >>> N =[[1,1,1],[2,2,2],[3,3,3]] >>> [M[row][col]*N[row][col]for row in range(3)for col in range(2)] [1, 2, 8, 10, 21, 24]
理解列表解析:
基于运行在当前python下测试,map调用比等效的for循环要快两倍,二列表解析往往比map调用要稍快一些,速度上的差距是来自于底层实现上,map和列表解析是在解释器中以C语言的速度来运行的,毕python的for循环代码在PVM中进行运行要快的多。
生成器(generator)
成器就是一种迭代器拥有next方法并且行为与迭代器完全相同,所以生成器也可以用于Python的for循环中。
#首先创建一个最简单的生成器 >>> def gensquares(N): #通过gensquares创建生成器 for i in range(N): yield i **2 >>> for i in gensquares(5): #使用for循环遍历,跟迭代器一样 print(i,end=' : ') 0 : 1 : 4 : 9 : 16 :
如果想看看for循环里发生了什么,直接调用生成器函数
>>> x = gensquares(5) >>> x <generator object gensquares at 0x0000000003587B88>
调用生成器函数返回一个生成器
1 >>> generator = gensquares(5) 2 ''' 3 第一次调用生成器的next方法时,生成器才开始执行生成器函数(而不是构建生成器时),直到遇到yield时暂停执行(挂起),并且yield的参数将作为此次next方法的返回值; 4 ''' 5 >>> next(generator) 6 0 7 >>> next(generator) 8 1 9 >>> next(generator) 10 ''' 11 之后每次调用生成器的next方法,生成器将从上次暂停执行的位置恢复执行生成器函数,直到再次遇到yield时暂停,并且同样的,yield的参数将作为next方法的返回值; 12 ''' 13 4 14 >>> next(generator) 15 9 16 #当next函数到达生成器末尾时候,会抛出StopIteration异常 17 >>> next(generator) 18 Traceback (most recent call last): 19 File "<pyshell#40>", line 1, in <module> 20 next(generator) 21 StopIteration
在生成器迭代的过程中接入另一个生成器
1 >>> def generator(): #创造一个生成器函数 2 yield 1 3 yield 2 4 yield from range(10) #接入另一个生成器 5 >>> for i in generator():print(i,end="|") #通过for循环遍历 6 1|2|0|1|2|3|4|5|6|7|8|9|
send函数
send是除next外另一个恢复生成器的方法。其实next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。
1 >>> def gen(): 2 for i in range(10): 3 x = yield i 4 print(x) 5 >>> x = gen() 6 >>> next(x) 7 0 8 >>> x.send(44) 9 44 10 1 11 >>> x.send(24) 12 24 13 2 14 >>> next(x) 15 None 16 3
浙公网安备 33010602011771号