在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个有一个元素的列表
你应该考虑使用dict
types,而不是预先初始化列表。 字典查找的成本很小,并且与访问任意列表元素的成本相当。
而当使用映射时,你可以写:
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),则数组类是有用的。 但是,它也不需要预先初始化。