在 C++ 中,我可以创建一个数组,如...
int* a = new int[10];
在python中,我只知道我可以声明一个列表,而不是附加一些项目,或者像..
l = [1,2,3,4]
l = range(10)
我可以按给定的大小初始化列表,比如 c++,并且不做任何赋值吗?
(tl;博士:您的问题的确切答案是numpy.empty
or numpy.empty_like
,但您可能不在乎并且可以使用myList = [None]*10000
.)
您可以将列表初始化为所有相同的元素。使用非数字值在语义上是否有意义(如果您使用它,稍后会出错,这是一件好事)或类似 0 的东西(不寻常?如果您正在编写稀疏矩阵或 ' 可能有用默认值应该是 0 并且你不担心错误)取决于你:
>>> [None for _ in range(10)]
[None, None, None, None, None, None, None, None, None, None]
(这里_
只是一个变量名,你可以使用i
.)
你也可以这样做:
>>> [None]*10
[None, None, None, None, None, None, None, None, None, None]
您可能不需要对此进行优化。您还可以在每次需要时附加到数组:
>>> x = []
>>> for i in range(10):
>>> x.append(i)
哪个最好?
>>> def initAndWrite_test():
... x = [None]*10000
... for i in range(10000):
... x[i] = i
...
>>> def initAndWrite2_test():
... x = [None for _ in range(10000)]
... for i in range(10000):
... x[i] = i
...
>>> def appendWrite_test():
... x = []
... for i in range(10000):
... x.append(i)
python2.7中的结果:
>>> import timeit
>>> for f in [initAndWrite_test, initAndWrite2_test, appendWrite_test]:
... print('{} takes {} usec/loop'.format(f.__name__, timeit.timeit(f, number=1000)*1000))
...
initAndWrite_test takes 714.596033096 usec/loop
initAndWrite2_test takes 981.526136398 usec/loop
appendWrite_test takes 908.597946167 usec/loop
python 3.2 中的结果:
initAndWrite_test takes 641.3581371307373 usec/loop
initAndWrite2_test takes 1033.6499214172363 usec/loop
appendWrite_test takes 895.9040641784668 usec/loop
[None]*10000
正如我们所看到的,在 python2 和 python3 中都使用这个习语可能会更好。但是,如果一个人正在做比赋值更复杂的事情(例如任何复杂的生成或处理列表中的每个元素的事情),那么开销就变成了成本中毫无意义的一小部分。也就是说,如果您对列表中的元素做任何合理的事情,那么担心这种优化还为时过早。
然而,这些都是低效的,因为它们会通过内存,在这个过程中写入一些东西。在 C 中这是不同的:未初始化的数组充满了随机垃圾内存(旁注:已从系统重新分配,并且当您分配或无法 mlock 和/或在关闭程序时无法删除内存时可能会带来安全风险)。这是一个设计选择,旨在加速:C 语言的制造者认为最好不要自动初始化内存,这是正确的选择。
这不是渐近加速(因为它是O(N)
),但是例如,在用您真正关心的内容覆盖之前,您不需要先初始化整个内存块。如果可能的话,这相当于 (pseudo-code) 之类的东西x = list(size=10000)
。
如果你想在 python 中使用类似的东西,你可以使用numpy
数值矩阵/N 维数组操作包。具体来说,numpy.empty
或numpy.empty_like
这是你问题的真正答案。
你可以使用这个:[None] * 10
. 但这不会是“固定大小”,您仍然可以追加、删除……这就是列表的制作方式。
您可以将其设为元组 ( tuple([None] * 10)
) 以固定其宽度,但同样,您将无法更改它(并非在所有情况下,仅当存储的项目是可变的时)。
另一种更接近您要求的选项不是列表,而是collections.deque
具有最大长度的列表。这是最大尺寸,但它可以更小。
import collections
max_4_items = collections.deque([None] * 4, maxlen=4)
但是,只需使用一个列表,并习惯“pythonic”的做事方式。
这更像是一个警告而不是一个答案。
在其他答案中看到后my_list = [None] * 10
,我很受诱惑并设置了一个这样的数组speakers = [['','']] * 10
,并且非常后悔,因为结果list
并没有像我想象的那样表现。
我求助于:
speakers = []
for i in range(10):
speakers.append(['',''])
[['','']] * 10
似乎创建了一个list
where 后续元素是第一个元素的副本。
例如:
>>> n=[['','']]*10
>>> n
[['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', '']]
>>> n[0][0] = "abc"
>>> n
[['abc', ''], ['abc', ''], ['abc', ''], ['abc', ''], ['abc', ''], ['abc', ''], ['abc', ''], ['abc', ''], ['abc', ''], ['abc', '']]
>>> n[0][1] = "True"
>>> n
[['abc', 'True'], ['abc', 'True'], ['abc', 'True'], ['abc', 'True'], ['abc', 'True'], ['abc', 'True'], ['abc', 'True'], ['abc', 'True'], ['abc', 'True'], ['abc', 'True']]
而使用.append
选项:
>>> n=[]
>>> for i in range(10):
... n.append(['',''])
...
>>> n
[['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', '']]
>>> n[0][0] = "abc"
>>> n
[['abc', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', '']]
>>> n[0][1] = "True"
>>> n
[['abc', 'True'], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', '']]
我确信 ninjagecko 接受的答案确实试图提及这一点,遗憾的是我太厚了,无法理解。
收官,保重!
像这样初始化列表并不是真正的 python 方式。无论如何,您可以像这样初始化一个列表:
>>> l = [None] * 4
>>> l
[None, None, None, None]
另请注意,当您在 C++ 中使用数组时,您可能有一些不同的需求,这些需求在 Python 中以不同的方式解决:
Python 通过NumPy解决了对数组的需求,其中包括创建已知大小的数组的方法:
from numpy import *
l = zeros(10)
Python 没有内置的东西来支持这一点。你真的需要优化它吗,因为我认为追加不会增加那么多开销。
但是,您可以执行类似l = [None] * 1000
.
或者,您可以使用生成器。
your_list = [None]*size_required
fix_array = numpy.empty(n, dtype = object)
其中 n 是数组的大小
虽然它有效,但它可能不是最好的主意,因为您必须为此目的导入一个库。希望这可以帮助!