如果切片复制引用了此行为,为什么?

DeL*_*n88 1 python reference list slice

根据,蟒蛇副本引用时切片。我尝试了以下方法:

>>> a=[1,2,3]
>>> b=a[:]
>>> b[1]=0
>>> a
[1, 2, 3]
>>> b
[1, 0, 3]
>>> map(id,a)
[14508376, 14508352, 14508328]
>>> map(id,b)
[14508376, 14508400, 14508328]
Run Code Online (Sandbox Code Playgroud)

为什么不b[1]=0改变a[1](如果b[1]确实是对同一个对象的引用,人们可能会想到这种情况)?相反,它似乎会生成一个新的引用/ id并更改新的对象。在哪里我可以更详细地阅读此行为?

che*_*ner 5

假设您从开始a = [1,2,3]。在Python的数据模型中,这意味着a引用内存中的对象:

a -> [ * | * | * ]
       |   |   |
       v   v   v
       1   2   3
Run Code Online (Sandbox Code Playgroud)

使用b = a,您只需将另一个名称指向同一对象:

a -> [ * | * | * ] <- b
       |   |   |
       v   v   v
       1   2   3
Run Code Online (Sandbox Code Playgroud)

b[1] = 0更改相同的引用a[1] = 0将:

           0
           ^
           |
a -> [ * | * | * ] <- b
       |       |
       v       v
       1   2   3
Run Code Online (Sandbox Code Playgroud)

2仍在内存中,可能通过其他名称直接或间接引用,但不再通过ab再次引用。)


使用b = a[:],您可以创建一个新列表,但是该新列表包含对同一对象的引用:

a -> [ * | * | * ]
       |   |   |
       v   v   v
       1   2   3
       ^   ^   ^
       |   |   |
b -> [ * | * | * ]
Run Code Online (Sandbox Code Playgroud)

现在,当您编写时b[1] = 0,您并不需要更改a[1],因为ab是不同的列表对象。

a -> [ * | * | * ]
       |   |   |
       v   v   v
       1   2   3
       ^       ^
       |       |
b -> [ * | * | * ]
           |
           v
           0
Run Code Online (Sandbox Code Playgroud)

Ned Batchelder的博客文章(以及随后的PyCon演讲)很好地概述了Python的名称模型。