根据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并更改新的对象。我可以在任何地方更详细地了解这种行为吗?
答案 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
仍在内存中,可能通过其他名称直接或间接引用,但不再通过a
或b
引用。)
使用b = a[:]
,创建一个新的 list ,但是该新列表包含对同一对象的引用:
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的名称模型。