无法理解浅拷贝

use*_*645 1 python deep-copy shallow-copy

>>> a = [1,2,3]
>>> b = a[:]
>>> id(a[0]) == id(b[0])
True
>>> b[0] = 99
>>> id(a[0]) == id(b[0])
False
Run Code Online (Sandbox Code Playgroud)

我理解,为了制作浅色副本,我们可以使用切片,还有一个复制模块.但是为什么写入"b"索引会改变id.

Bri*_*ius 5

第1部分:为什么呼叫b[0] = 99原因a[0] == b[0] >> False

您的问题的答案是,当您这样做时b[0] = 99,您不会"修改B字段中的某个字段指向的内存地址",您实际上会更改B字段中的某个字段所指向的位置.

a = [1,2,3]  
Run Code Online (Sandbox Code Playgroud)

现在a包含对list对象的引用,该对象又包含对三个int对象的三个引用.

b = a[:]
Run Code Online (Sandbox Code Playgroud)

现在b指的是一个list对象(与引用的对象不同a),并且包含对三个int对象的三个引用,即引用的对象a.

id(a) == id(b)
#False
Run Code Online (Sandbox Code Playgroud)

是的,因为a并且b是对不同list对象的引用.

id(a[0]) == id(b[0])
#True
Run Code Online (Sandbox Code Playgroud)

是的,因为a[0]1对象的引用,所以也是b[0].只有一个1对象,它由a[0]和引用b[0]

b[0] = 99  
# ^^^^^^ THIS IS NOT WHAT THE WIKIPEDIA ARTICLE IS DESCRIBING
Run Code Online (Sandbox Code Playgroud)

b仍指同一个旧list对象,但b[0]现在引用该99对象.您只是取代了其中一个引用list由提到b一个新的参照不同的对象.你没有修改任何a指向的对象!

id(a[0]) == id(b[0]) 
#False
Run Code Online (Sandbox Code Playgroud)

错误,因为1对象与对象不是同一个99对象.


第2部分:维基百科文章谈论的是什么呢?

下面是一个复制操作的示例,其中您实际上是"修改B的一个字段指向的内存地址",因此您可以看到复制对象中的后续更改.

a = [[1],[2],[3]]
Run Code Online (Sandbox Code Playgroud)

alist对象的引用,但现在该list对象包含对对象的三个引用list,每个引用都包含对对象的引用int.

b = a[:]
Run Code Online (Sandbox Code Playgroud)

和以前一样,你已经b引用了一个新的,不同的list对象,它指的是SAME中的三个list对象a.这是证据:

id(a) == id(b)
# False
Run Code Online (Sandbox Code Playgroud)

错,因为和以前一样a,b是对不同list对象的引用.

id(a[0]) == id(b[0]) 
#True
Run Code Online (Sandbox Code Playgroud)

诚然,因为之前,双方a[0]b[0]指向同一个对象.这次它是一个list不是不可变int对象,与对象不同- 我们实际上可以改变list对象的内容! 这是它变得与众不同的地方:

b[0][0] = 99  
Run Code Online (Sandbox Code Playgroud)

我们做到了 - 我们改变了所引用的对象的内容listb[0]

a[0][0]
# 99 !!!!!!!!!!!!!!  Wikipedia doesn't need to be edited!
Run Code Online (Sandbox Code Playgroud)

看到?被提到的名单" list被称作a现指的99对象,而不是1对象,因为它是相同的list,你有访问b[0][0] = 99.简单,呵呵;)

id(a[0]) == id(b[0])
#True !!!
Run Code Online (Sandbox Code Playgroud)

诚然,因为虽然我们改变了什么内容的a[0]引用,我们并没有改变参考自身a[0]b[0]-这是更接近什么维基百科的文章在"浅复制"部分描述.