目前我正在使用一个列表,希望得到类似下面的内容:
verts = list (1000)
我应该使用数组吗?
目前我正在使用一个列表,希望得到类似下面的内容:
verts = list (1000)
我应该使用数组吗?
我首先想到的是:
verts = [None]*1000
但是你真的需要预先初始化它吗?
a=[[]]*2; a[0].append('foo');
现在检查 a[1]
,你会感到震惊。相比之下,a=[[] for k in range(2)]
就可以正常工作。 - Joachim W不太清楚为什么大家都反对你想做这个 - 有几种情况下,你会想要一个固定大小的初始化列表。而你已经正确地推断出在这些情况下使用数组是合理的。
import array
verts=array.array('i',(0,)*1000)
对于非Python程序员来说,(0,)*1000
表示创建一个包含1000个零的元组。逗号强制Python将 (0)
视为元组,否则它会被解释为数字0。一种明显但可能不太有效的方法是
verts = [0 for x in range(1000)]
请注意,这可以很容易地扩展到二维。例如,要获取一个10x100的“数组”,可以执行:
verts = [[0 for x in range(100)] for y in range(10)]
在任何编程语言中,初始化一个固定大小的数组是完全可以接受的;它不像程序员想在while(true) 循环中放置一个break语句。相信我,特别是如果元素只是被覆盖而不是仅仅添加/减去的情况,就像许多动态编程算法一样,你不想在代码中使用append语句和检查元素是否已经被初始化(那是很多代码啊)。
object = [0 for x in range(1000)]
这将对程序员试图实现的目标起作用。
@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
verts = list(xrange(1000))
这将给你一个由1000个元素组成的列表,它被初始化为0-999的值。由于list
首先执行__len__
以确定新列表的大小,因此效率应该相当高。
aDict = {}
aDict[100] = fetchElement()
putElement(fetchElement(), fetchPosition(), aDict)
putElement
函数可以在任何给定位置存储项目。如果您需要检查集合是否包含给定索引处的元素,则更符合Python风格的写法是:
if anIndex in aDict:
print "cool!"
比:
if not myList[anIndex] is None:
print "cool!"
由于后者假定您的集合中没有None
元素。如果发生这种情况,您的代码将无法正常工作。
如果您迫切需要性能,并因此尝试预初始化变量并编写最快的代码,则应更改语言。最快的代码无法在Python中编写。您应该尝试使用C语言,并实现包装器以从Python调用预初始化和预编译代码。
如果不了解更多关于问题域的信息,很难回答你的问题。 除非你确定需要做更多的事情,否则初始化列表的Pythonic方式是:
verts = []
你真的看到了性能问题吗?如果是这样,性能瓶颈是什么? 不要试图解决你没有的问题。动态填充一个数组到1000个元素的性能成本可能对你真正想编写的程序来说是完全无关紧要的。
如果列表中的内容始终是特定的原始固定长度类型(例如char、int、float),那么数组类很有用。但是,它也不需要预先初始化。
这个:
lst = [8 for i in range(9)]
lst = [0] * 7
会创建7个只有一个元素的列表
[0] * 7
的结果是 [0, 0, 0, 0, 0, 0, 0]
,这是一个包含7个元素的列表。你是在描述某个很旧的 Python 版本的行为吗? - FooFmylist = [0] * 4
,然后执行mylist[0] = 12
,mylist
返回[12, 0, 0, 0]
。 - toonarmycaptain