根据 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 名称模型的出色概述。
