在Python中将列表初始化为已知数量的元素

时间:2009-02-06 18:58:53

标签: python arrays list

现在我正在使用一个列表,并期待像:

verts = list (1000)

我应该使用数组吗?

9 个答案:

答案 0 :(得分:322)

首先想到的是:

verts = [None]*1000

但你真的需要预先初始化吗?

答案 1 :(得分:69)

不太确定为什么每个人都给你一个很难想要这样做的事情 - 有几种情况你需要一个固定大小的初始化列表。而且你已经正确地推断出阵列在这些情况下是合理的。

import array
verts=array.array('i',(0,)*1000)

对于非pythonistas,(0,)*1000术语创建一个包含1000个零的元组。逗号强制python将(0)识别为元组,否则它将被评估为0。

我使用了元组而不是列表,因为它们通常具有较低的开销。

答案 2 :(得分:60)

一种显而易见但可能效率不高的方法是

verts = [0 for x in range(1000)]

请注意,这可以轻松扩展到2维。 例如,要获得10x100“阵列”,您可以执行

verts = [[0 for x in range(100)] for y in range(10)]

答案 3 :(得分:30)

在任何编程语言中,想要初始化固定大小的数组是完全可以接受的;它不像程序员想要在while(true)循环中放入break语句。相信我,特别是如果元素只是被覆盖而不仅仅是添加/减少,就像许多动态编程算法的情况一样,你不想乱用append语句并检查元素是否已被删除即时初始化(这是很多代码)。

object = [0 for x in range(1000)]

这将适用于程序员正在努力实现的目标。

答案 4 :(得分:17)

@Steve已经对你的问题给出了一个很好的答案:

verts = [None] * 1000

警告:正如@Joachim Wuttke指出的那样,必须使用不可变元素初始化列表。 [[]] * 1000无法按预期工作,因为您将获得1000个相同列表的列表(类似于C中相同列表的1000个点的列表)。像int,str或tuple这样的不可变对象会很好。

替代

调整列表大小很慢。以下结果并不令人惊讶:

>>> N = 10**6

>>> %timeit a = [None] * N
100 loops, best of 3: 7.41 ms per loop

>>> %timeit a = [None for x in xrange(N)]
10 loops, best of 3: 30 ms per loop

>>> %timeit a = [None for x in range(N)]
10 loops, best of 3: 67.7 ms per loop

>>> a = []
>>> %timeit for x in xrange(N): a.append(None)
10 loops, best of 3: 85.6 ms per loop

但如果您没有非常大的列表,那么调整大小的速度并不是很慢。您应该考虑使用列表推导并直接使用正确的值填充列表,而不是使用单个元素(例如None)和固定长度初始化列表以避免列表调整大小。例如:

>>> %timeit a = [x**2 for x in xrange(N)]
10 loops, best of 3: 109 ms per loop

>>> def fill_list1():
    """Not too bad, but complicated code"""
    a = [None] * N
    for x in xrange(N):
        a[x] = x**2
>>> %timeit fill_list1()
10 loops, best of 3: 126 ms per loop

>>> def fill_list2():
    """This is slow, use only for small lists"""
    a = []
    for x in xrange(N):
        a.append(x**2)
>>> %timeit fill_list2()
10 loops, best of 3: 177 ms per loop

与numpy的比较

对于庞大的数据集,numpy或其他优化的库要快得多:

from numpy import ndarray, zeros
%timeit empty((N,))
1000000 loops, best of 3: 788 ns per loop

%timeit zeros((N,))
100 loops, best of 3: 3.56 ms per loop

答案 5 :(得分:4)

你可以这样做:

verts = list(xrange(1000))

这将为您提供1000个元素的列表,并且恰好使用0-999之间的值进行初始化。当list首先__len__确定新列表的大小时,它应该相当有效。

答案 6 :(得分:0)

您应该考虑使用dict类型而不是预先初始化的列表。字典查找的成本很小,与访问任意列表元素的成本相当。

使用映射时,您可以写:

aDict = {}
aDict[100] = fetchElement()
putElement(fetchElement(), fetchPosition(), aDict)

putElement函数可以在任何给定位置存储项目。如果你需要检查你的集合是否包含给定索引的元素,那么写更多Pythonic:

if anIndex in aDict:
    print "cool!"

比:

if not myList[anIndex] is None:
    print "cool!"

由于后者假设您的集合中没有真正的元素可以是None。如果发生这种情况 - 你的代码行为不端。

如果您迫切需要性能,这就是您尝试预先初始化变量并尽可能编写最快代码的原因 - 请更改您的语言。最快的代码不能用Python编写。您应该尝试使用C语言并实现包装器以从Python调用预先初始化和预编译的代码。

答案 7 :(得分:0)

此:

 lst = [8 for i in range(9)]

创建一个列表,元素被初始化8

但是这个:

lst = [0] * 7

将创建7个列表,其中包含一个元素

答案 8 :(得分:-2)

如果不了解有关问题域的更多信息,很难回答您的问题。 除非你确定需要做更多的事情,否则初始化列表的pythonic方法是:

verts = []

您是否真的看到了性能问题?如果是这样,性能瓶颈是什么? 不要试图解决你没有的问题。将数组动态填充到1000个元素的性能成本可能与您真正想要编写的程序完全不相关

如果列表中的内容始终是特定的原始固定长度类型(例如char,int,float),则数组类很有用。但是,它也不需要预先初始化。