2

假设我想像这样制作一个空的 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”中使用列表上的乘法?

4

2 回答 2

4

列表推导是通常的答案。不像序列乘法那样干净,但最好的:

[[0.0]*3 for _ in xrange(4)]

请注意,对于许多需要值网格的应用程序,您正在做一些numpy ndarrays 可以做得更快、更清洁的事情。

于 2013-08-21T22:52:34.467 回答
3

这是在官方 Python 编程常见问题解答中,如如何创建多维列表?.

常见问题解答提出了三种可能性:

  1. 创建所需长度的列表,然后循环替换每个元素。
  2. 使用列表推导。
  3. 首先使用类似 numpy.array 的东西而不是多维列表。

我认为大多数 Python 开发人员会以与常见问题解答中列出的完全相反的顺序提出这些建议……但没有人会抱怨其中任何一个。所以:

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.

于 2013-08-21T22:57:19.077 回答