[英]Creating a list with sequential numbers fast
from time import time
mylist1 = []
mylist2 = []
start1 = time()
for i in range(100000000):
mylist1.append(i)
end1 = time()
start2 = time()
mylist2 = [0] * 100000000
end2 = time()
print(end1-start1, end2-start2)
当我对两个动作进行计时以填充列表时,使用for循环可获得14秒,而mylist2 = [0] * 100000000
0.5秒
因此,如果我需要一次插入大量项目,似乎可以使用第二种方法。
但是,如果我做第二件事,则必须为所有插入相同的数字,或者手动键入要重复的数字。
有办法执行吗
for i in range(100000000):
mylist1.append(i)
这个动作导致[0,1,2,3,...,n]的速度很好?
如果速度很快,则代码不一定必须简短。
对于完整的可移植性, 如Prune所述, list(range(N))
将获得最佳性能。 就是说,如果您仅以Python 3.5或更高版本为目标,则可以使用PEP 448的其他解包概括来加快其运行速度,方法如下:
[*range(N)]
注意,这是固定的节省,而不是每个项目; 它所做的只是绕过内置名称空间中的list
查找,以及常规list
构造函数的广义函数调用分派和__init__
参数处理。 因此,当您谈论1亿件商品时,节省下来的钱将浪费在噪音中。 所有这一切都是(在我的3.6安装中)将固定开销减少了170±10 ns(例如list(range(0))
每次调用花费417 ns,而[*range(0)]
每次调用花费247 ns)。
但是在特定情况下,还有一个更快的选择:
mynotlist = range(100000000)
在现代Python中, range
对象是完整的序列 ,它们是不可变的。 因此,您可以构造它们,对其进行索引,对其进行切片,计算它们的长度,前后对其进行迭代,检查成员资格(在O(1)
为int
s,这与成员资格测试为O(n)
list
不同)等。它们缺少的与非可变性无关的功能是串联和重复(使用+
和*
),尽管您可以使用itertools
函数(例如chain
(用于串联)和islice
cycle
(用于重复))来模拟这些功能 。
如果您不需要突变序列,只需阅读一下即可,使用“ raw” range
是迄今为止的最佳选择 ; range
s是惰性的,不占用内存,同时仍然非常有效地产生它们的值。 懒惰可能很重要; list(range(100000000))
将需要(在64位Python上) list
本身加上其包含的所有int
的3.45 GB内存; range(100000000)
需要48 个字节 。 考虑到内存的节省,即时生成值的琐碎成本是值得的。
如果需要可变性,仍然可以在内存上节省一点。 如果可以选择numpy
,则可以满足sacul的回答 ; 如果不是这样, Python的数组模块将为您节省一些时间和大量内存。 相比:
list(range(100000000))
array
替代:
array.array('I', range(100000000))
花费更少的约10%的时间(微基准有list
在3.39秒,与array.array
在3.07秒),并且消耗更少的存储器(下〜391 MB,对所述〜3529 MB的的list
的int
或多个)。 array
的主要代价是值的范围有限(例如,对于'I'
,四字节unsigned int
只能将值存储在range(2**32)
; q
/ Q
格式代码的最大范围,使用两倍的内存,将是range(-2**63, 2**63)
/ range(2**64)
)。
尝试列出range
输出:
mylist3 = list(range(100000000))
我将此添加到您的测试中并获得了以下时间:
append: 18.42
all-0: 0.23
list: 2.63 <== The new one
既然您说需要速度,我认为np.arange
是最好的选择,它甚至比创建所有0
秒的列表还要快。 以下是我机器上的时间:
import timeit
import numpy as np
def m1(n=100000000):
mylist = []
for i in range(n):
mylist.append(i)
return mylist
def m2(n=100000000):
return [0] * n
def m3(n=100000000):
return list(range(n))
def m4(n=100000000):
return np.arange(n)
>>> timeit.timeit(m1,number=1)
17.615584995000972
>>> timeit.timeit(m2,number=1)
0.7669911839911947
>>> timeit.timeit(m3,number=1)
9.909814337006537
>>> timeit.timeit(m4,number=1)
0.5374436590063851
请注意, np.arange()
返回np.array
。 如果需要将其转换回列表,则会失去速度。 最好只使用数组...
def m4(n=100000000):
return np.arange(n).tolist()
>>> timeit.timeit(m4,number=1)
11.485261309993803
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.