现在我正在使用一个列表,并期待像:
verts = list (1000)
我应该使用数组吗?
答案 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或其他优化的库要快得多:
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),则数组类很有用。但是,它也不需要预先初始化。