81

在 C++ 中,我可以创建一个数组,如...

int* a = new int[10];

在python中,我只知道我可以声明一个列表,而不是附加一些项目,或者像..

l = [1,2,3,4]
l = range(10)

我可以按给定的大小初始化列表,比如 c++,并且不做任何赋值吗?

4

9 回答 9

110

(tl;博士:您的问题的确切答案是numpy.emptyor 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.emptynumpy.empty_like

这是你问题的真正答案。

于 2012-05-16T11:05:21.420 回答
15

你可以使用这个:[None] * 10. 但这不会是“固定大小”,您仍然可以追加、删除……这就是列表的制作方式。

您可以将其设为元组 ( tuple([None] * 10)) 以固定其宽度,但同样,您将无法更改它(并非在所有情况下,仅当存储的项目是可变的时)。

另一种更接近您要求的选项不是列表,而是collections.deque具有最大长度的列表。这是最大尺寸,但它可以更小。

import collections
max_4_items = collections.deque([None] * 4, maxlen=4)

但是,只需使用一个列表,并习惯“pythonic”的做事方式。

于 2012-05-16T11:12:06.550 回答
8

这更像是一个警告而不是一个答案。
在其他答案中看到后my_list = [None] * 10,我很受诱惑并设置了一个这样的数组speakers = [['','']] * 10,并且非常后悔,因为结果list并没有像我想象的那样表现。
我求助于:

speakers = []
for i in range(10):
    speakers.append(['',''])

[['','']] * 10似乎创建了一个listwhere 后续元素是第一个元素的副本。
例如:

>>> 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 接受的答案确实试图提及这一点,遗憾的是我太厚了,无法理解。
收官,保重!

于 2019-02-01T16:52:42.053 回答
6

您可以使用数组模块来做到这一点。array 模块是 python 标准库的一部分:

from array import array
from itertools import repeat

a = array("i", repeat(0, 10))
# or
a = array("i", [0]*10)

重复函数将 0 值重复 10 次。它比 [0]*10 更节省内存,因为它不分配内存,而是重复返回相同的数量 x 次。

于 2019-01-18T14:51:37.170 回答
4

像这样初始化列表并不是真正的 python 方式。无论如何,您可以像这样初始化一个列表:

>>> l = [None] * 4
>>> l
[None, None, None, None]
于 2012-05-16T10:57:25.543 回答
3

另请注意,当您在 C++ 中使用数组时,您可能有一些不同的需求,这些需求在 Python 中以不同的方式解决:

  1. 您可能只需要一组项目;Python 列表完美地处理了这个用例。
  2. 您可能需要一适当的同类项目。Python 列表不是存储数组的好方法。

Python 通过NumPy解决了对数组的需求,其中包括创建已知大小的数组的方法:

from numpy import *

l = zeros(10)
于 2012-05-16T11:14:11.910 回答
2

Python 没有内置的东西来支持这一点。你真的需要优化它吗,因为我认为追加不会增加那么多开销。

但是,您可以执行类似l = [None] * 1000.

或者,您可以使用生成器。

于 2012-05-16T10:57:38.377 回答
1
your_list = [None]*size_required
于 2012-05-16T11:01:38.270 回答
1
fix_array = numpy.empty(n, dtype = object)

其中 n 是数组的大小

虽然它有效,但它可能不是最好的主意,因为您必须为此目的导入一个库。希望这可以帮助!

于 2017-06-29T14:00:06.593 回答