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]的速度很好吗?
如果速度很快,代码不一定必须简短。
答案 0 :(得分:3)
要获得完全的可移植性,list(range(N))
将获得最佳性能as Prune notes。也就是说,如果您仅以Python 3.5或更高版本为目标,则可以使用PEP 448's additional unpacking generalizations通过以下方式加快速度:
[*range(N)]
请注意,这是固定的节省,而不是每个项目;它所做的只是绕过内置名称空间中的list
查找,以及常规__init__
构造函数的广义函数调用分派和list
参数处理。因此,当您谈论1亿件商品时,节省下来的钱将浪费在噪音中。这一切都是(在我的3.6安装中)将固定开销减少了170±10 ns(例如,list(range(0))
每次调用花费417 ns,而[*range(0)]
每次调用花费247 ns)。
在某些情况下,还有一个更快的选择:
mynotlist = range(100000000)
在现代Python中,range
objects是full fledged sequences,它们是不可变的。因此,您可以构造它们,对其进行索引,对其进行切片,计算其长度,前后对其进行迭代,检查成员资格(在O(1)
中进行int
s的访问,与list
中进行成员资格测试的{ {1}})等。它们缺少的唯一与非可变性无关的功能是串联和重复(使用O(n)
和+
),尽管您可以使用itertools
functions像{{ 3}}(用于串联),chain
和islice
ing(用于重复)。
如果您不需要对序列进行突变,只需使用*
“原始”进行读取即可,到目前为止, 是最佳选择; range
是惰性的,不占用内存,同时仍然非常有效地产生其值。懒惰可能很重要; range
将需要(在64位Python上)3.45个 giga 字节的内存用于list(range(100000000))
本身及其包含的所有list
; int
需要48个字节。在节省内存的情况下,即时生成值的琐碎成本是值得的。
如果需要可变性,仍然可以在内存上节省一点。如果选择range(100000000)
,则cycle
可以满足您的要求;如果没有,sacul's answer将为您节省一些时间,并节省大量 内存。相比:
numpy
list(range(100000000))
替代项:
array
节省大约10%的时间(微基准测试在 array.array('I', range(100000000))
时为3.39秒,而list
在3.07秒时),并且消耗的 far 更少的内存(不到391 MB) ,而array.array
中list
的〜3529 MB)。 int
的主要成本是有限的值范围(例如,对于array
,四个字节的'I'
只能在unsigned int
中存储值; {{1}的最大范围} / range(2**32)
格式代码,使用两倍的内存,将是q
/ Q
)。
答案 1 :(得分:2)
尝试列出range
输出的列表:
mylist3 = list(range(100000000))
我将此添加到您的测试中并得到了以下时间:
append: 18.42
all-0: 0.23
list: 2.63 <== The new one
答案 2 :(得分:2)
由于您说需要速度,因此我认为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