假设我想制作一个空的3x4 2d数组。
x = [[0.0]*3]*4
但是,使用上面的代码,
print x[0] is x[1] # Output = True
含义,
x[1][1] = 5.0
print x # Output = [[0.0, 5.0, 0.0],
# [0.0, 5.0, 0.0],
# [0.0, 5.0, 0.0],
# [0.0, 5.0, 0.0]]
为了绕过创建此列表,其中包含对同一列表的4个相同引用,我一直在做类似的事情:
y = [[0.0]*3, [0.0]*3, [0.0]*3, [0.0]*3]
其中
print y[0] is y[1] # Output = False
y[1][1] = 5.0
print y # Output = [[0.0, 0.0, 0.0],
# [0.0, 5.0, 0.0],
# [0.0, 0.0, 0.0],
# [0.0, 0.0, 0.0]]
另一种方法是使用列表理解
z = [[0.0]*3 for x in range(4)]
但是,这似乎仍然有点难看。
有没有办法让数组'y'或'z'所有引用在优雅格式中是唯一的,例如在'x'中使用列表中的乘法?
答案 0 :(得分:4)
列表理解是通常的答案。不像序列乘法一样干净,但是最好的可用:
[[0.0]*3 for _ in xrange(4)]
请注意,对于您想要一个值网格的许多应用程序,您正在做一些numpy ndarrays可以做得更快更干净的事情。
答案 1 :(得分:3)
这是官方Python编程常见问题解答,How do I create a multidimensional list?。
常见问题解答提出了三种可能性:
我认为大多数Python开发人员会以与他们在FAQ中列出的完全相反的顺序提出这些建议......但是没有人会抱怨他们中的任何一个。所以:
a = np.zeros((3, 4))
a = [[0.0]*3 for _ in range(4)]
a = [None] * 4
for i, _ in enumerate(a):
a[i] = [0.0]*3
如果你发现自己经常这么做(而不是使用numpy),你总是可以将它包装在一个函数中。事实上,这通常是处理看起来很丑的任何的最佳方式,即使你正在尽可能地进行python。所以:
def make_matrix(r, c):
return [[0.0]*c for _ in range(r)]
然后它尽可能清楚:
a = make_matrix(3, 4)
itertools
有一个名为repeat
的函数,它等同于*
的迭代器版本。文档显示了一些等效的纯Python代码,因此很容易使其适应(浅或深)复制每个代表的对象:
def repeat(obj, times):
for _ in range(times):
yield copy.copy(obj)
list(repeat([0.0]*3, 4))
我认为这不是更具可读性 - 特别是如果你想在多个级别使用它:
list(repeat(list(repeat(0.0, 3)), 4))
...即使你将它包装在一个让你感觉良好的函数中:
def srepeat(object, times):
return list(repeat(object, times))
srepeat(srepeat(0.0, 3), 4)
...如果你将它包装在一个处理多个维度的函数中,你只需重新创建make_matrix
。