我是Python的初学者,所以请你解释一下为什么会出现以下情况。 请考虑以下代码:
>>> A = [1, 2, 3, 4]
>>> B = A[0:2]
>>> print id(A) == id(B)
False
>>> print id(A[0]) == id(B[0])
True #Why?
>>> A[0] = 9
>>> A
[9, 2, 3, 4]
>>> B
[1, 2]
>>> print id(A[0]) == id(B[0])
False #Contradiction?
从上面的代码中可以看出,我将列表A切片并将其复制到B,但是,为什么print id(A[0]) == id(B[0])
在第一个上评估True
,但在我更改A中的任何一个时相反还是B的价值?
答案 0 :(得分:2)
当你执行B = A[0:2]
时,最终基本上会这样做,作为其中的一部分:B[0] = A[0]
。因此1
中的对象(整数A[0]
)与B[0]
中的对象相同。
当你设置A[0] = 9
时,那些对象就不一样了。
另外,正如@ŁukaszRogalski指出CPython缓存小整数。所以我们有A[0] == 1 == B[0]
和id(1) == id(1)
。
A[0] == 9
,9 != 1 == B[0]
和id(9) != id(1)
。
答案 1 :(得分:2)
试试这个:
id(1) == id(1) #True
原因是这些数字常量将在整个程序中重复使用。因此它就像存储器1的存储器一样,然后在程序中提到1的任何地方,将使用相同的存储器,因此只会创建对该存储器的引用。对象保持不变。
答案 2 :(得分:1)
基本上,无论何时复制/切片,python都不会从列表中的每个项目创建新对象。
但是,虽然这不会对不可变对象造成任何麻烦,但是你应该小心使用可变对象:
In [22]: A = [[1, 2], 2, 3, 4]
In [23]: B = A[0:2]
In [24]: id(A[0]) == id(B[0])
Out[24]: True
In [27]: A[0][1] = 99
In [28]: B
Out[28]: [[1, 99], 2]
在这种情况下,您可以使用copy.deepcopy
创建切片的新对象:
In [32]: import copy
In [33]: B = copy.deepcopy(A[0:2])
In [34]: A[0][1] = 5
In [35]: B
Out[35]: [[1, 99], 2]
In [36]: id(A[0]) == id(B[0])
Out[36]: False
^
New Object