Skip to main content
 首页 » 编程设计

python之如果切片复制引用为什么会出现这种行为

2025年05月04日23leader

根据 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 并更改新对象。我可以在哪里更详细地了解这种行为?

请您参考如下方法:

假设您从 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 仍在内存中,可能通过其他名称直接或间接引用,但不再通过 a 或 b 引用。 )


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

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

现在当你写 b[1] = 0 时,你并没有改变 a[1],因为 a 和 b 是不同的列表对象。

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

Ned Batchelder 的 blog post (以及随后的 PyCon talk )是对 Python 名称模型的出色概述。