Python:为什么这个列表的理解速度比等效的for循环慢5000倍?

2024-04-19 19:18:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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时停止

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

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))

Tags: 文件csvin列表fordatatimeas
2条回答

这是答案

在这部法典中

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作用域中,如果i >= 1000

但是在这段代码中,没有break关键字(因为您使用了列表理解)

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 ...]不会在i < 1000时中断,而是始终读取,直到enumerate(reader)完成。这与前面的代码不同,在前面的代码中,for作用域将在i >= 1000时中断。但不是为了列表理解

例如,您可以使用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)]

正如@Barmar所说,您的列表理解正在迭代您的所有csv文件行,它不会在索引1000处停止,要在索引1000处停止,您可以使用islice

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

与您的列表理解等效的代码,以便更好地理解花费如此长时间的原因:

with open("file.csv", 'r', newline = "\n") as f:
    reader = csv.reader(f, delimiter = ",")
    data = []
    for i, r in enumerate(reader):
        if i < 1000:
            data.append(r)
        # else iterate till the end of file

相关问题 更多 >