迭代器和生成器 1. 迭代 1.1 迭代的定义 在 Python 中,给定一个 list 或 tuple,我们可以通过 for 循环来遍历这个 list 或 tuple ,这种遍历就是迭代。
迭代案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 for char in 'liangdianshui' : print ( char , end = ' ' ) print ('\n' ) list1 = [1 ,2 ,3 ,4 ,5 ] for num1 in list1 : print ( num1 , end = ' ' ) print ('\n' ) dict1 = {'name' :'两点水' ,'age' :'23' ,'sex' :'男' } for key in dict1 : print ( key , end = ' ' ) print ('\n' ) for value in dict1.values() : print ( value , end = ' ' ) print ('\n' ) for x , y in [ (1 ,'a' ) , (2 ,'b' ) , (3 ,'c' ) ] : print ( x , y )
1.2 迭代器 迭代器 是一个可以记住遍历的位置的对象,从集合的第一个元素开始访问,直到所有的元素被访问完结束. 迭代器有两个基本的方法:iter()
和 next()
, 且 字符串 ,列表 或 元组 对象都可用于创建迭代器, 迭代器对象可以使用常规 for
语句进行遍历,也可以使用 next()
函数来遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 str1 = 'liangdianshui' iter1 = iter (str1) list1 = [1 ,2 ,3 ,4 ] iter2 = iter (list1) tuple1 = (1 ,2 ,3 ,4 ) iter3 = iter (tuple1) for x in iter1 : print (x, end=' ' ) while True : try : print (next (iter3)) except StopIteration : break
2. list 生成式(列表生成式) 2.1 创建 list 1 2 3 4 list1 = list (range (1 ,31 )) print (list1)
1 2 3 4 5 6 7 8 9 10 11 12 13 print ('\n' .join([' ' .join(f'{x} *{y} ={x * y} ' for x in range (1 , y+1 )) for y in range (1 , 10 )]))输出结果: 1 *1 =1 2 *1 =2 2 *2 =4 3 *1 =3 3 *2 =6 3 *3 =9 4 *1 =4 4 *2 =8 4 *3 =12 4 *4 =16 5 *1 =5 5 *2 =10 5 *3 =15 5 *4 =20 5 *5 =25 6 *1 =6 6 *2 =12 6 *3 =18 6 *4 =24 6 *5 =30 6 *6 =36 7 *1 =7 7 *2 =14 7 *3 =21 7 *4 =28 7 *5 =35 7 *6 =42 7 *7 =49 8 *1 =8 8 *2 =16 8 *3 =24 8 *4 =32 8 *5 =40 8 *6 =48 8 *7 =56 8 *8 =64 9 *1 =9 9 *2 =18 9 *3 =27 9 *4 =36 9 *5 =45 9 *6 =54 9 *7 =63 9 *8 =72 9 *9 =81
2.2 列表生成式 list 生成式的语法格式:
结果 for 元素 in 集合
把集合中的元素依次提取出来, 然后在表达式中应用元素, 最后把表达式的结果添加到结果中 结果 for 元素 in 集合 if 筛选条件
把条件成立的元素从集合中提取出来, 然后在表达式中应用元素, 最后把表达式的结果添加到结果中 1 2 3 4 5 list1=[x * x for x in range (1 , 11 )] print (list1) list1= [x * x for x in range (1 , 11 ) if x % 2 == 0 ] print (list1)
1 2 3 4 list1 = [(x, y) for x in range (2 ) for y in range (3 )] print (list1)[(0 , 0 ), (0 , 1 ), (0 , 2 ), (1 , 0 ), (1 , 1 ), (1 , 2 )]
3. 生成器(generator
) 在 Python 中,这种一边循环一边计算的机制,称为生成器:generator
在 Python 中,使用了 yield 的函数被称为生成器(generator) 在调用生成器运行的过程中,每次遇到 yield
时函数会暂停并保存当前所有的运行信息,返回 yield 的值。并在下一次执行 next()方法时从当前位置继续运行
3.1 生成器创建 生成器创建 最简单的方法就是把一个列表生成式的 []
改成 ()
1 2 3 4 5 6 gen= (x * x for x in range (10 )) print (gen)输出的结果: <generator object <genexpr> at 0x0000000002734A40 >
创建 List
和 generator
的区别仅在于最外层的 []
和 ()
。 生成器并不真正创建数字列表,而是返回一个生成器 这个生成器在每次计算出一个条目后,把这个条目产生(yield)
出来。
生成器表达式使用了 惰性计算 (lazy evaluation,也有翻译为“延迟求值”,我以为这种按需调用 call by need 的方式翻译为惰性更好一些),只有在检索时才被赋值(evaluated
),所以在列表比较长的情况下使用内存上更有效。
3.2 遍历生成器的元素 1 2 3 4 5 6 7 8 9 10 gen = (x*x for x in range (10 )) for i in gen: print (i, end=' ' ) while True : try : print (next (gen), end=' ' ) except StopIteration: break
3.3 以函数的形式实现生成器 1 2 3 4 5 6 7 8 9 10 11 12 def odd (): print ('step 1' ) yield 1 print ('step 2' ) yield 3 print ('step 3' ) yield 5 o = odd() print (next (o)) print (next (o)) print (next (o))
可以看到,odd 不是普通函数,而是 generator,在执行过程中,遇到 yield 就中断,下次又继续执行。 执行 3 次 yield 后,已经没有 yield 可以执行了,如果你继续打印 print(next(o)),就会报错的。 所以通常在 generator 函数中都要对错误进行捕获。
1 2 3 4 5 6 7 8 9 10 def fibon (n ): a = b = 1 for i in range (n): yield a a, b = b, a + b for x in fibon(10 ): print (x , end = ' ' )
3.4 打印杨辉三角 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def triangles (): lists = [1 ] while True : yield lists lists.append(0 ) lists = [lists[i - 1 ] + lists[i] for i in range (len (lists))] n = 0 for t in triangles(): print (t) n = n + 1 if n == 5 : break 输出结果: [1 ] [1 , 1 ] [1 , 2 , 1 ] [1 , 3 , 3 , 1 ] [1 , 4 , 6 , 4 , 1 ]
4. 迭代器和生成器结合 4.1 反向迭代 反向迭代仅仅当对象的大小可 预先确定
或者对象实现了 __reversed__()
的特殊方法时才能生效。 如果两者都不符合,那你必须先将对象转换为一个列表才行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Countdown : def __init__ (self, start ): self.start = start def __iter__ (self ): n = self.start while n > 0 : yield n n -= 1 def __reversed__ (self ): n = 1 while n <= self.start: yield n n += 1 for rr in reversed (Countdown(10 )): print (rr, end=' ' ) for rr in Countdown(10 ): print (rr, end=' ' )
4.2 同时迭代多个序列 zip()
函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
1 2 3 4 5 names = ['laingdianshui' , 'twowater' , '两点水' ] ages = [18 , 19 , 20 ] for name, age in zip (names, ages): print (name, age, end=', ' )
利用zip()
函数,我们还可把一个 key 列表和一个 value 列表生成一个 dict(字典)
1 2 3 4 5 6 names = ['laingdianshui' , 'twowater' , '两点水' ] ages = [18 , 19 , 20 ] dict1 = dict (zip (names, ages)) print (dict1)