快速创建具有序号的列表

时间:2018-09-20 23:57:51

标签: python python-3.x

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]的速度很好吗?

如果速度很快,代码不一定必须简短。

3 个答案:

答案 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 objectsfull fledged sequences,它们是不可变的。因此,您可以构造它们,对其进行索引,对其进行切片,计算其长度,前后对其进行迭代,检查成员资格(在O(1)中进行int s的访问,与list中进行成员资格测试的{ {1}})等。它们缺少的唯一与非可变性无关的功能是串联和重复(使用O(n)+),尽管您可以使用itertools functions像{{ 3}}(用于串联),chainisliceing(用于重复)。

如果您不需要对序列进行突变,只需使用*“原始”进行读取即可,到目前为止, 是最佳选择range是惰性的,不占用内存,同时仍然非常有效地产生其值。懒惰可能很重要; range将需要(在64位Python上)3.45个 giga 字节的内存用于list(range(100000000))本身及其包含的所有listint需要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.arraylist的〜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