Python:为什么弹出队列比forin block快?

2024-04-20 08:45:24 发布

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

我一直在编写一个python脚本来分析csv。其中一些文件相当大(100万到200万条记录),而脚本需要几个小时才能完成。在

我改变了记录的处理方式,从for-in循环改为while循环,而且速度提升非常显著。演示如下:

>>> def for_list():
...     for d in data:
...             bunk = d**d
... 
>>> def while_list():
...     while data:
...             d = data.pop(0)
...             bunk = d**d
... 
>>> data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> import timeit
>>> timeit.timeit(for_list)
1.0698931217193604
>>> timeit.timeit(while_list)
0.14515399932861328

快了一个数量级。我从来没有看过python字节码,但我认为它可能很有说服力,但结果发现while_list有更多的指令。在

怎么回事?这里有没有一个原则可以适用于其他项目?是否存在forwhile快十倍的情况?在

编辑:正如@HappyLeapSecond所指出的,我不太清楚timeit内部到底发生了什么,差异如下:

^{pr2}$

这让我很奇怪,我的“真正的”脚本加速这么简单的变化。我最好的猜测是迭代方法需要更多的交换?我有一个40G的交换分区,脚本可以填充大约15-20G。弹出会减少交换吗?在


Tags: 文件csvin脚本fordatadef方式
1条回答
网友
1楼 · 发布于 2024-04-20 08:45:24

while_list正在对全局{}进行变异。timeit.timeit不重置data的值。^默认情况下,{}调用for_list和{}一百万次。在第一次调用while_list之后,对while_list的后续调用在执行0个循环后返回,因为data已经是空的。在

在每次调用for_list和{}之前,需要重置data的值,以执行公平的基准测试。在


import timeit

def for_list(data):
    for d in data:
        bunk = d ** d


def while_list(data):
    while data:
        d = data.pop(0)
        bunk = d ** d

data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

print(timeit.timeit('data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; for_list(data)', 'from __main__ import for_list'))
# 0.959696054459

print(timeit.timeit('data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; while_list(data)', 'from __main__ import while_list'))
# 2.40107011795

pop(0)是一个O(n)操作。在长度为n的循环中执行该操作会使while_list具有总体时间复杂度{},而{}的复杂度为for_list。因此,正如预期,for_list更快,n的长度越大,优势就越大。在

相关问题 更多 >