Wil*_*ill 9 python optimization for-loop while-loop
我一直在研究python脚本来分析CSV.其中一些文件相当大(1-2百万条记录),脚本需要数小时才能完成.
我改变了记录从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
Run Code Online (Sandbox Code Playgroud)
几乎快一个数量级.我从来没有看过python字节码,但我可能会说,但事实证明它while_list有更多的指令.
那么这里发生了什么?这里有原则我可以申请其他课程吗?是否有for比这快十倍的情况while?
编辑:正如@HappyLeapSecond指出的那样,我并不完全清楚内部发生了什么timeit .差异消失了以下:
>>> def for_list():
... data = [x for x in range(1000)]
... for d in data:
... bunk = d**d
...
>>> def while_list():
... data = [x for x in range(1000)]
... while data:
... d = data.pop(0)
... bunk = d**d
>>> timeit.timeit(while_list, number=1000)
12.006330966949463
>>> timeit.timeit(for_list, number=1000)
11.847280025482178
Run Code Online (Sandbox Code Playgroud)
这让我的"真实"剧本如此简单地加速变得非常奇怪.我最好的猜测是迭代方法需要更多交换?我有一个40G交换分区,脚本填充大约15-20G.弹出会减少交换吗?
unu*_*tbu 12
while_list正在改变全球data.timeit.timeit不重置的值data.默认情况下,每次timeit.timeit调用for_list和 while_list一百万次.在第一次调用之后,执行0循环后返回的while_list后续调用while_list因为data已经为空.
您需要data在每次调用之前重置值for_list并while_list执行公平的基准测试.
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
Run Code Online (Sandbox Code Playgroud)
pop(0)是一个O(n)操作.与复杂度相比,在长度循环内执行该操作n会while_list产生总体时间复杂度.正如预期的那样,速度越快,优势越大,长度越大.O(n**2)O(n)for_listfor_listndata