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

现在我正在使用一个列表,并期待着像这样的东西:

verts = list (1000) 

我应该使用数组吗?

我想到的第一件事是:

 verts = [None]*1000 

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

不太清楚为什么每个人都想给你一个很难的时间 – 有几种情况你想要一个固定大小的初始化列表。 而且你已经正确地推断出在这些情况下数组是合理的。

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

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

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

一个显而易见的可能不是有效的方法是

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

请注意,这可以很容易地扩展到二维。 例如,要获得一个10×100的“arrays”,你可以做

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

在任何编程语言中,想要初始化一个固定大小的数组是一个完全可以接受的事情; 它不像程序员想要在while(true)循环中放置break语句。 相信我,特别是如果元素只是被覆盖,而不是像许多dynamic编程algorithm的情况那样只是被加/减,你不想乱用append语句并检查元素是否被初始化还在飞行(这是很多代码绅士)。

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

这将为程序员试图实现的function起作用。

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

 verts = [None] * 1000 

警告:正如@Joachim Wuttke指出的,列表必须用一个不可变的元素初始化。 [[]] * 1000不能正常工作,因为您将得到1000个相同列表的列表(类似于C列表中的1000列表)。 象int,str或者元组这样的不可变对象将会很好。

备择scheme

调整列表的速度很慢。 以下结果并不令人惊讶:

 >>> 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 

但是如果你没有很大的列表,resize不是很慢。 不要使用单个元素(例如None )和固定长度来初始化列表,以避免列表大小调整,您应该考虑使用list comprehensions并直接用正确的值填充列表。 例如:

 >>> %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 

你可以这样做:

 verts = list(xrange(1000)) 

这将给你一个1000个元素的大小列表,恰好用0-999的值初始化。 由于list __len__一个__len__来调整新的列表,它应该是相当有效的。

这个:

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

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

但是这个:

 list = [0] * 7 

会创build7个有一个元素的列表

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

而当使用映射时,你可以写:

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

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

 if anIndex in aDict: print "cool!" 

比:

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

因为后者假设你的collections中没有真正的元素可以是None 。 如果发生这种情况 – 你的代码会出错。

如果你迫切需要性能,这就是为什么你试图预先初始化你的variables,并写出最快的代码 – 改变你的语言。 最快的代码不能用Python编写。 你应该尝试使用C,并实现包装从Python调用你预先初始化和预编译的代码。

在不了解问题域的情况下,很难回答你的问题。 除非您确定需要做更多的事情,否则初始化列表的Python方法是:

 verts = []

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

如果列表中的东西总是成为特定的基本固定长度types(例如char,int,float),则数组类是有用的。 但是,它也不需要预先初始化。