假如我们要迭代两个列表,如下:
names = ['Cecilia', 'Lise', 'Marie'] counts = [len(n) for n in names] print(counts) # [7, 4, 5]
下面我们来迭代这两份列表,根据长度迭代:
longset_name = None max_count = 0 for i in range(len(names)): count = counts[i] if count > max_count: longset_name = names[i] max_count = count print(longset_name) # Cecilia
上面整个循环比较乱,是通过下标names和counts这两个列表里的元素。下面改用enumerate实现,但是仍然不理想:
for i, name in enumerate(names): count = counts[i] if count > max_count: longset_name = name max_count = count
下面通过zip函数实现,可以是代码个让你更加简洁:
for name, count in zip(names, counts): if count > max_count: longset_name = name max_count = count
zip函数能把两个或更多的iterator封装成惰性生成器(lazy generator)。每次循环,从各个迭代器获取各自的下一个元素,并放在一个数组里。然后元素可以拆分for循环的那些变量中。
zip函数还有个好处就是每次从哪些迭代器里各自取一个元素,即使源列表很长,程序也不会因占用内存过多而崩溃。
但是,当zip函数里面的长度不一致了,会怎么样呢?,如下,names列表增加一个元素再遍历:
names.append('Rose') for name, count in zip(names, counts): print(f'{name}: {count}') # Cecilia: 7 # Lise: 4 # Marie: 5
可以看到新加的名字并没有打印出来。因为zip函数这样设计的:只有其中一个迭代器处理完毕,就不会往下走了,所以循环的次数实际是最短的列表的长度。
所以,一般不一样长的列表,就不要使用zip函数了。可以使用另外一个zip_longest函数,这个函数位于内置的iterator模块里。
import itertools for name, count in itertools.zip_longest(names, counts): print(f'{name}: {count}') # Cecilia: 7 # Lise: 4 # Marie: 5 # Rose: None
当其中有些列表走完了,那么会填充默认值None。
要点
- 内置的zip函数可以同时遍历多个迭代器
- zip会创建惰性生成器,每次值生成一个元组,减少内存占用
- 如果迭代器程度不一致,其中一个迭代完毕后,zip会自动停止
- 如果想按照长度长的来遍历,那就改内置的itertools模块的zip_longest函数
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)