2D 列表在试图修改单个值时有奇怪的行为

可能的复制品:
Python 列表列表 中的意外特性

所以我对 Python 相对比较陌生,在使用2D List 时遇到了麻烦。

这是我的密码:

data = [[None]*5]*5
data[0][0] = 'Cell A1'
print data

以下是输出(为便于阅读而格式化) :

[['Cell A1', None, None, None, None],
['Cell A1', None, None, None, None],
['Cell A1', None, None, None, None],
['Cell A1', None, None, None, None],
['Cell A1', None, None, None, None]]

为什么每一行都被赋值?

32575 次浏览

这就形成了一个对 一样列表有五个引用的列表:

data = [[None]*5]*5

使用下面这样的代码可以创建五个独立的列表:

>>> data = [[None]*5 for _ in range(5)]

现在,它完成了你所期望的任务:

>>> data[0][0] = 'Cell A1'
>>> print data
[['Cell A1', None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None]]

在 python 中,每个变量都是一个对象,因此是一个引用。首先创建一个包含5个 Nones 的数组,然后构建一个具有5倍相同对象的数组。

正如包含列表的 序列类型的 python 库引用所说的那样

还要注意的是,这些副本是浅表的; 嵌套结构不会被复制:

>>> lists = [[]] * 3
>>> lists
[[], [], []]
>>> lists[0].append(3)
>>> lists
[[3], [3], [3]]

发生的情况是,[[]]是一个包含空列表的单元素列表,因此[[]] * 3的所有三个元素都是(指向)这个单个空列表。修改列表的任何元素都可以修改这个列表。

你可以这样创建一个不同列表的列表:

>>> lists = [[] for i in range(3)]
>>> lists[0].append(3)
>>> lists[1].append(5)
>>> lists[2].append(7)
>>> lists
[[3], [5], [7]]