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

时间:2018-07-10 20:52:38

标签: python list reference slice

根据this,python在切片时会复制引用。我尝试了以下方法:

>>> 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]

为什么b[1]=0不会更改a[1](如果有人认为b[1]确实是对同一对象的引用,应该是这种情况)?相反,它似乎会生成一个新的引用/ id并更改新的对象。我可以在任何地方更详细地了解这种行为吗?

1 个答案:

答案 0 :(得分:5)

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

a -> [ * | * | * ]
       |   |   |
       v   v   v
       1   2   3

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

a -> [ * | * | * ] <- b
       |   |   |
       v   v   v
       1   2   3

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

           0
           ^
           |
a -> [ * | * | * ] <- b
       |       |
       v       v
       1   2   3

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


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

a -> [ * | * | * ]
       |   |   |
       v   v   v
       1   2   3
       ^   ^   ^
       |   |   |
b -> [ * | * | * ]

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

a -> [ * | * | * ]
       |   |   |
       v   v   v
       1   2   3
       ^       ^
       |       |
b -> [ * | * | * ]
           |
           v
           0

内德·巴切尔德(Ned Batchelder)的blog post(及其后的PyCon talk)很好地概述了Python的名称模型。