为什么 Python 中变量赋值的行为不同?

Yan*_*ang 2 python variables

我是Python新手,我对以下代码感到很困惑:

示例1:

n = 1
m = n
n = 2
print(n)   # 2
print(m)   # 1
Run Code Online (Sandbox Code Playgroud)

示例2:

names = ["a", "b", "c"]
visitor = names
names.pop()
print(names)      # ['a', 'b']
print(visitor)    # ['a', 'b']
Run Code Online (Sandbox Code Playgroud)

示例 1 显示n是 1 并且m是 1。然而,示例 2 显示names是 ['a', 'b'],并且visitor也是 ['a', 'b']。

对我来说,示例 1 和示例 2 很相似,所以我想知道为什么结果如此不同?谢谢。

jua*_*aga 5

这是根本的区别。在第一种情况下,对于整数:

n = 2
Run Code Online (Sandbox Code Playgroud)

不会改变任何n东西。这是因为赋值不是突变。然而,在第二种情况下:

names.pop()
Run Code Online (Sandbox Code Playgroud)

您正在调用的方法.pop是一个mutator 方法

就是这样。请注意,您可以使用列表获得与第一种情况完全相同的行为:

>>> n = []
>>> m = n
>>> n = ['hi']
>>> print(n)
['hi']
>>> print(m)
[]
Run Code Online (Sandbox Code Playgroud)

因为赋值并没有改变任何东西。

注意,int对象不公开任何修改器方法,即它们是“不可变的”。当然,这不是魔法

我们可以使用实现细节来深入了解 an 的内部int并实际改变它。

>>> import ctypes
>>> my_integer = 1337
>>> pointer = ctypes.cast(id(my_integer), ctypes.POINTER(ctypes.c_int))
>>> pointer[6] = 99
>>> my_integer
99
Run Code Online (Sandbox Code Playgroud)

好的,现在,让我们重新创建原始示例,这次使用此方法来改变 immutable int

>>> n = 1337 # not messing with lower valued ints because they are cached
>>> m = n
>>> ctypes.cast(id(n), ctypes.POINTER(ctypes.c_int))[6] = 999
>>> print(n)
999
>>> print(m)
999
Run Code Online (Sandbox Code Playgroud)

请注意,上面的内容是根据 Python 3.11 编写的。更高版本可能会更改对象的布局int,因此pointer[6] = whatever不保证正常工作。