Effective Python 第8条:使用zip函数同时遍历两个迭代器

Effective Python 第8条:使用zip函数同时遍历两个迭代器,第1张

Effective Python 第8条:使用zip函数同时遍历两个迭代器

假如我们要迭代两个列表,如下:

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。

要点

  1. 内置的zip函数可以同时遍历多个迭代器
  2. zip会创建惰性生成器,每次值生成一个元组,减少内存占用
  3. 如果迭代器程度不一致,其中一个迭代完毕后,zip会自动停止
  4. 如果想按照长度长的来遍历,那就改内置的itertools模块的zip_longest函数

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5689618.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存