在C++中,我可以创建一个像...一样的数组
int* a = new int[10];
Run Code Online (Sandbox Code Playgroud)
在python中,我只知道我可以声明一个列表,而不是追加一些项目,或者像...
l = [1,2,3,4]
l = range(10)
Run Code Online (Sandbox Code Playgroud)
我可以按照给定的大小初始化列表,比如c ++,不做任何分配吗?
nin*_*cko 57
(tl;博士:你的问题的确切答案是numpy.empty
或numpy.empty_like
,但你可能不在乎,可以逃脱使用myList = [None]*10000
.)
您可以将列表初始化为所有相同的元素.在语义上是否有意义使用非数字值(如果你使用它会产生错误,这是一件好事)或类似0(不寻常?如果你正在编写稀疏矩阵或'默认'值应为0,您不担心错误)取决于您:
>>> [None for _ in range(10)]
[None, None, None, None, None, None, None, None, None, None]
Run Code Online (Sandbox Code Playgroud)
(这里_
只是一个变量名,您可以使用i
.)
你也可以这样做:
>>> [None]*10
[None, None, None, None, None, None, None, None, None, None]
Run Code Online (Sandbox Code Playgroud)
您可能不需要优化它.您还可以在每次需要时附加到数组:
>>> x = []
>>> for i in range(10):
>>> x.append(i)
Run Code Online (Sandbox Code Playgroud)
哪个最好?
>>> 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)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
python 3.2中的结果:
initAndWrite_test takes 641.3581371307373 usec/loop
initAndWrite2_test takes 1033.6499214172363 usec/loop
appendWrite_test takes 895.9040641784668 usec/loop
Run Code Online (Sandbox Code Playgroud)
我们可以看到,[None]*10000
在python2和python3中做成语可能更好.但是,如果一个人做了比赋值更复杂的事情(例如生成或处理列表中每个元素的任何复杂事件),那么开销就变成了成本的无意义的一小部分.也就是说,如果您对列表中的元素做了任何合理的事情,这种优化还为时过早.
然而,这些都是低效的,因为它们通过记忆,在过程中写一些东西.在C中,这是不同的:未初始化的数组中充满了随机垃圾内存(旁注:已从系统重新分配,当您在关闭程序时分配或未能进行mlock和/或无法删除内存时可能存在安全风险).这是一个设计选择,专为加速而设计:C语言的制造者认为最好不要自动初始化内存,这是正确的选择.
这不是渐近加速(因为它是O(N)
),但是例如,在用你真正关心的东西覆盖之前,你不需要首先初始化你的整个内存块.如果可能的话,这等同于(伪代码)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)
Run Code Online (Sandbox Code Playgroud)
但是,只需使用一个列表,并习惯"pythonic"的做事方式.
您可以使用数组模块来完成。数组模块是python标准库的一部分:
from array import array
from itertools import repeat
a = array("i", repeat(0, 10))
# or
a = array("i", [0]*10)
Run Code Online (Sandbox Code Playgroud)
重复功能将 0 值重复 10 次。它比 [0]*10 的内存效率更高,因为它不分配内存,而是重复返回相同数量的 x 次。
这与其说是回答,不如说是警告。
在其他答案中看到后my_list = [None] * 10
,我很受诱惑并设置了这样的数组speakers = [['','']] * 10
,并且非常后悔,因为结果list
并没有像我想象的那样表现。
我求助于:
speakers = []
for i in range(10):
speakers.append(['',''])
Run Code Online (Sandbox Code Playgroud)
由于[['','']] * 10
出现以产生list
其中后续元素是第一元素的副本。
例如:
>>> 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']]
Run Code Online (Sandbox Code Playgroud)
而有.append
选项:
>>> n=[]
>>> for i in range(10):
... n.append(['',''])
...
>>> n
[['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', '']]
>>> n[0][0] = "abc"
>>> n
[['abc', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', '']]
>>> n[0][1] = "True"
>>> n
[['abc', 'True'], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', '']]
Run Code Online (Sandbox Code Playgroud)
我确信 ninjagecko 接受的答案确实试图提及这一点,遗憾的是我太厚了无法理解。
结束,保重!