繁体   English   中英

快速创建具有序号的列表

[英]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的的listint或多个)。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM