Python - 在这种情况下如何解释将数据分配给数组

tha*_*eow 2 python arrays

请参阅下面的代码,为什么这样做

array[0][0] = 'Tadaaaa'
Run Code Online (Sandbox Code Playgroud)

改变了5个元素而不是1个?

首先,创建一个空数组:

x, y = 5, 3

# when you multiply it's copying, so the ids of each item is the same
array = [[set()] * y] * x
array
Run Code Online (Sandbox Code Playgroud)

我会得到:

[[set(), set(), set()],
 [set(), set(), set()],
 [set(), set(), set()],
 [set(), set(), set()],
 [set(), set(), set()]]
Run Code Online (Sandbox Code Playgroud)

然后为元素赋值:

array[3][2].add('BBC')
array
Run Code Online (Sandbox Code Playgroud)

我会得到:

[[{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}]]
Run Code Online (Sandbox Code Playgroud)

但当我这样做时:

array[0][0] = 'Tadaaaa'
array
Run Code Online (Sandbox Code Playgroud)

我明白了:

[['Tadaaaa', {'BBC'}, {'BBC'}],
 ['Tadaaaa', {'BBC'}, {'BBC'}],
 ['Tadaaaa', {'BBC'}, {'BBC'}],
 ['Tadaaaa', {'BBC'}, {'BBC'}],
 ['Tadaaaa', {'BBC'}, {'BBC'}]]
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?

我以为我会得到这样的东西:

[['Tadaaaa', {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}]]
Run Code Online (Sandbox Code Playgroud)

che*_*ner 5

首先,这些不是数组; 他们是名单.

其次,using使用*创建对同一 set对象的引用列表,而不是对不同set对象的引用列表.

>>> x = [set()]*3
>>> id(x[0]), id(x[1]), id(x[2])
(4297985280, 4297985280, 4297985280)
Run Code Online (Sandbox Code Playgroud)

相反,使用列表推导来确保set()每个元素调用一次.

>>> x = [set() for _ in range(3)]
>>> id(x[0]), id(x[1]), id(x[2])
(4298169136, 4298363424, 4298363656)
Run Code Online (Sandbox Code Playgroud)

您可以使用嵌套列表推导来获取所需的嵌套列表:

>>> x, y = 5, 3
>>> array = [[set() for _ in range(y)] for _ in range(x)]
>>> for x in array:
...   map(id, x)
...
[4298169136, 4298363424, 4298363656]
[4297985280, 4298363888, 4298364120]
[4298364352, 4298364584, 4298364816]
[4298365048, 4298365280, 4298365512]
[4298365744, 4298365976, 4298366208]
Run Code Online (Sandbox Code Playgroud)

如您所见,数组中的每个元素都是一个不同的set对象.

  • 因为第一个调用`array [3] [2]`引用的可变对象的方法(这是由列表的*every*元素引用的相同对象).第二个更改存储在`array [0] [0]`中的引用,用引用`str`对象覆盖先前的引用.您应该阅读https://nedbatchelder.com/text/names.html. (2认同)