在for循环中哪个更pythonic:zip或enumerate?

Lit*_*les 3 python for-loop iterable

考虑到可扩展性和可读性,其中哪一个被认为是更加pythonic?使用enumerate:

group = ['A','B','C']
tag = ['a','b','c']

for idx, x in enumerate(group):
    print(x, tag[idx])
Run Code Online (Sandbox Code Playgroud)

或使用zip:

for x, y in zip(group, tag):
    print(x, y)
Run Code Online (Sandbox Code Playgroud)

我问的原因是我一直在混合两者.我应该遵循一种标准方法,但它应该是什么?

dex*_*cko 9

虽然其他人指出它zip实际上比 更Pythonic enumerate,但我来这里是为了看看它是否更有效。根据我的测试,与简单地并行访问和使用多个列表中的项目zip相比,速度大约快 10% 到 20% 。enumerate

这里我有三个并行访问的(相同)长度递增的列表。当列表的长度超过几个项目时,zip/enumerate 的时间比率低于零,并且 zip 速度更快。

在 R-Studio 中绘制

我使用的代码:

import timeit

setup = \
"""
import random
size = {}
a = [ random.randint(0,i+1) for i in range(size) ]
b = [ random.random()*i for i in range(size) ]
c = [ random.random()+i for i in range(size) ]
"""
code_zip = \
"""
data = []
for x,y,z in zip(a,b,c):
    data.append(x+z+y)
"""
code_enum = \
"""
data = []
for i,x in enumerate(a):
    data.append(x+c[i]+b[i])
"""
runs = 10000
sizes = [ 2**i for i in range(16) ]
data = []

for size in sizes:
    formatted_setup = setup.format(size)
    time_zip = timeit.timeit(code_zip, formatted_setup, number=runs)
    time_enum = timeit.timeit(code_enum, formatted_setup, number=runs)
    ratio = time_zip/time_enum
    row = (size,time_zip,time_enum,ratio)
    data.append(row)

with open("testzipspeed.csv", 'w') as csv_file:
    csv_file.write("size,time_zip,time_enumerate,ratio\n")

    for row in data:
        csv_file.write(",".join([ str(i) for i in row ])+"\n")
Run Code Online (Sandbox Code Playgroud)


shx*_*hx2 7

毫无疑问,zip更像是pythonic.它不需要您使用变量来存储索引(您不需要),并且使用它可以统一处理列表,而使用enumerate,迭代一个列表,并索引另一个列表,即非 - 均匀处理.

但是,您应该知道zip仅在两个列表中较短的一个中运行的警告.为了避免重复别人的答案,我在这里只提供一个参考:别人的回答.

@ user3100115恰当地指出在python2中,你应该更喜欢使用itertools.izipover zip,因为它的懒惰性质(更快和更高的内存效率).在python3中zip已经表现得像py2了izip.