首页 > 解决方案 > Python:为什么这个列表理解比等效的 for 循环慢 5000 倍?

问题描述

我有一个 Python 脚本,它从 CSV 文件中读取 1000 行。

为什么csv.reader在列表理解中迭代对象比等效的显式 for 循环慢 4 个数量级?

time.time()以下是我机器上的代码片段及其时间(通过):

with open("file.csv", 'r', newline = "\n") as f:
    reader = csv.reader(f, delimiter = ",")
    data = [r for i, r in enumerate(reader) if i < 1000]

# Time: 26.459498167037964 s
with open("file.csv", 'r', newline = "\n") as f:
    reader = csv.reader(f, delimiter = ",")
    data = []
    for i, r in enumerate(reader):
        if i >= 1000:
            break
        data.append(r)

# Time: 0.005597114562988281 s

编辑:

根据答案,列表理解版本读取整个文件并仅选择满足条件的元素i < 1000,而显式循环在到达时停止i == 1000

对于这个问题的未来读者,@decenze 在评论中编写了最优雅的解决方案:

import csv
from itertools import islice

with open("file.csv", 'r', newline = "\n") as f:
    reader = csv.reader(f, delimiter = ",")
    data = list(islice(reader, 0, 1000))

标签: pythonperformancecsvlist-comprehension

解决方案


这是答案

在这段代码中,

with open("file.csv", 'r', newline = "\n") as f:
    reader = csv.reader(f, delimiter = ",")
    data = []
    for i, r in enumerate(reader):
        if i >= 1000:
            break
        data.append(r)

for范围内,for如果i >= 1000

但是在这段代码中,没有break关键字(因为你使用了 List Comprehension)

with open("file.csv", 'r', newline = "\n") as f:
    reader = csv.reader(f, delimiter = ",")
    data = [r for i, r in enumerate(reader) if i < 1000]

为什么这么慢?因为data = [r ...]不会中断 if i < 1000,但会一直读取直到enumerate(reader)完成。这与之前的代码不同,for如果i >= 1000. 但不适用于列表理解

您可以通过 using 或其他方法使用类似的代码raise StopIteration,例如

def LoopEnd():
    raise StopIteration()

with open("file.csv", 'r', newline = "\n") as f:
    reader = csv.reader(f, delimiter = ",")
    data = [r if i < 1000 else LoopEnd() for i, r in enumerate(reader)]

推荐阅读