Python:如何用我可以附加到的空值初始化嵌套列表

Python: How to initialize a nested list with empty values which i can append to

我正在学习 python 但碰壁了。 我正在尝试定义一个二维列表,稍后我可以使用它来附加值。这对应于 width *height

的网格

我尝试使用 [] 来初始化空列表,但是 wid 被忽略了。 我尝试使用 None 作为占位符,但我无法附加

wid = 3
hgt = 3
l1 = [[]*wid ] * hgt
l = [[None]*wid ] * hgt
l[1][1].append("something")

结果

l1: [[], [], []]

l: [[None, None, None], [None, None, None], [None, None, None]]

错误:

append: AttributeError: 'NoneType' object has no attribute 'append'

想要的结果:[[[], [], []], [[], [], []], [[], [], []]]

有两种方法

  1. 使用None作为占位符值,将其替换为l[1][1] = 5
  2. 使用空列表并追加新元素,l[1].append(5)

目前,您正在混合使用这两种方式。 l[1][1] returns 一个 None 值, 不是一个列表,而您正在尝试对其调用 append

无论如何,这里有一个常见的 python 陷阱。当你写

mylist = [[None]*2]*3

这有两个作用

  1. 创建列表[None, None]
  2. 使用此列表 3 次以创建另一个列表

关键是外部列表将包含内部列表的 3 个 副本 ,而不是 3 个不同的相同列表。所以,每次你修改其中一个,其余的也会被修改。因此,您需要复制内部列表。

然而,对于二维数组,最好的方法是使用 numpy

x = np.zeros(m, n)
x[1, 2] = 5

尝试在列表推导中使用列表推导:

>>> [ [ [] for i in range(wid) ] for i in range(hgt) ]
[[[], [], []], [[], [], []], [[], [], []]]

请注意,这比列表乘法更可取,因为每个列表都是唯一的。比较:

>>> x = [ [[] for i in range(wid)] for i in range(hgt) ]
>>> x[1][1].append('a')
>>> x
[[[], [], []], [[], ['a'], []], [[], [], []]]

对比

>>> y = [ [[]] * wid for i in range(hgt) ]
>>> y[1][1].append('a')
>>> y
[[[], [], []], [['a'], ['a'], ['a']], [[], [], []]]

对比

>>> z = [ [[]] * wid ] * hgt
>>> z[1][1].append('a')
>>> z
[[['a'], ['a'], ['a']], [['a'], ['a'], ['a']], [['a'], ['a'], ['a']]]

其中,在第二种和第三种情况下,'a'出现在多个单元格中!而使用 None 并不能避免这个问题:

>>> m = [ [None] * wid ] * hgt
>>> m
[[None, None, None], [None, None, None], [None, None, None]]
>>> if m[1][1] is None:
...     m[1][1] = ['a']
... else:
...     m[1][1].append('a')
...
>>> m
[[None, ['a'], None], [None, ['a'], None], [None, ['a'], None]]

tl;dr - 使用双列表理解。在我看来,无论如何,它是最易读的选项。

>>> x = 5
>>> y = 5
>>> [[None for _ in range(x)] for _ in range(y)]
[[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]]

不要使用 [[None]*x]*y 除非你真的知道你刚刚创建了共享引用。

如果你正在处理矩阵,你可以使用 numpy:

import numpy as np

my_matrix = np.zeros((rows, columns) # with 2 dimentions