Python 当我复制并编辑此列表时,到底发生了什么?
我根本不明白为什么会发生这种情况:Python 当我复制并编辑此列表时,到底发生了什么?,python,list,python-3.x,Python,List,Python 3.x,我根本不明白为什么会发生这种情况: A = [[1,0], [2,2]] B = list(A) print('start A:', A, 'start B:', B) A[0][0] = 999 print('end A:', A, 'end B:', B) 这将返回: start A: [[1, 0], [2, 2]] start B: [[1, 0], [2, 2]] end A: [[999, 0], [2, 2]] end B: [[999, 0], [2, 2]] 列表A和B最
A = [[1,0], [2,2]]
B = list(A)
print('start A:', A, 'start B:', B)
A[0][0] = 999
print('end A:', A, 'end B:', B)
这将返回:
start A: [[1, 0], [2, 2]] start B: [[1, 0], [2, 2]]
end A: [[999, 0], [2, 2]] end B: [[999, 0], [2, 2]]
列表A和B最终是相同的,即使我显式地从A复制了B。这只发生在我执行类似于A[0][0]=999的操作时;如果我用A[0]=999替换它,那么最后A和B是不同的
这背后的原因是什么?有没有办法以这种方式改变A而不影响B A和B都包含相同的两个列表 您的代码大致相当于:
x = [1, 0]
y = [2, 2]
A = [x, y]
B = [x, y]
操作
A[0][0]=999
实际上只是执行x[0]=999
。也就是说,它不修改A本身,而是修改列表的第一个元素x
。因为A和B都引用了x
,所以两者都会看到变化。像您这样简单的复制操作是浅层的,它只复制一层深的项,不会递归到嵌套结构中。你需要
>>> import copy
>>> A = [[1,0], [2,2]]
>>> B = copy.deepcopy(A)
>>> print('start A:', A, 'start B:', B)
start A: [[1, 0], [2, 2]] start B: [[1, 0], [2, 2]]
>>> A[0][0] = 999
>>> print('end A:', A, 'end B:', B)
end A: [[999, 0], [2, 2]] end B: [[1, 0], [2, 2]]
您正在创建原始列表的浅表副本,即新列表,其中包含对与原始列表相同的对象的新引用
修改新列表对象不会更改原始列表。修改新列表中的对象不会修改旧列表中的对象,因为它们是相同的
要获得完全独立的列表,请使用创建深度副本。a
和B
是计算机中相同内存块的两个不同名称
A
和B
是两个独立的列表对象,但是A[0]
和B[0]
是计算机中相同内存块的两个不同名称。从解释器中尝试以下操作:
id(B)
id(A)
id(B[0])
id(A[0])
Python代码操纵对对象的引用
分配给变量只是绑定一个名称以引用一个对象
列表由一组对对象的引用组成<代码>列表(A)查找A
中引用的所有对象,并创建一个包含所有相同对象引用的新列表。因此,如果A
是一个列表列表,list(A)
创建一个新列表,其中引用了A
中的相同列表。因此,在A
和新列表中都可以看到更改任何子列表
copy.deepcopy
的存在是为了在您需要某个内容的完整“深度”拷贝时帮助您解决此问题
一旦您学会将Python代码视为操纵对此类对象的引用,您将直观地了解代码何时可能最终从多个位置引用同一对象,尽管可能总会有一些模糊的情况让您感到惊讶。不,它们不是。它们是单独的列表对象。