Python 切片显示相同的 id 位置

Python slice shows same id location

我是 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的价值?

当您执行 B = A[0:2] 时,最终实际上是在执行此操作,作为其中的一部分:B[0] = A[0]。因此 A[0] 中的对象(整数 1)与 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)

试试这个:

id(1) == id(1) #True

原因是这些数字常量将在整个程序中重复使用。所以它就像给了一些内存来存储 1,然后在程序中提到 1 的任何地方,都会使用相同的内存,因此只会创建对该内存的引用。对象保持不变。

基本上,python 不会从列表中的每个项目创建新对象,只要您 copy/slice 一个它。

但是,虽然这不会对不可变对象造成任何麻烦,但您应该小心可变对象:

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