对以下两个代码片段的行为差异感到非常困惑,特别是对它们在 Python 概念中的可变性/不可变性中的行为的期望:
片段1
def some_function(x):
x[0] = 42
input = (3,)
_ = some_function(input)
print(input)
这会产生
TypeError: 'tuple' object does not support item assignment
,我的理解是因为元组是不可变的。还行吧。但是...
片段2
def some_function(x):
x = 42
input = (3,)
_ = some_function(input)
print(input)
哪个... 1]在尝试更改(不可变!)时不会抱怨/崩溃
x
- 与之前的片段2]相比,将input
打印为初始(3,)
,即,就好像 input
没有以任何方式“暴露”到 some_function
主体的赋值内部所采取的操作。
为什么有区别?这里发生了什么事?为什么元组的不可变性仅在第一个片段中显示?
这是一个示例,希望可以使其更容易理解:
x = (1, 2)
def func1():
x[0] = 42 # doesn't work
def func2():
x = (3, 4, 5) # does work!
当您写入
x[0] = something
时,脚本会在内存中找到 x
所指向的值并尝试修改它。
但是当您执行
x = something
时,脚本会在内存中创建一个新对象,并使 x
指向该新对象。
在您的示例中,
x
基本上只是对对象的引用。
在第一个代码块中,您尝试更改由 x
表示的对象,它是一个元组。
正如您正确指出的那样,元组在 Python 中是不可变的,这意味着您不能直接更改元组中包含的项目。
但是,您可以更改元组中的对象,只要该对象仍然相同即可。
class Test123:
abc = 10
a = Test123()
b = Test123()
print(a is b)
# --> False, as this is a different object and hence has a different identity
x = (a, )
# 1. Alter the tuple, doesn't work
x[0] = b
# --> Throws an error, as you're trying to change an immutable object
# 2. Alter the object within the tuple, works
x[0].abc = 123
# 3. Reassign x to another object, also works
old_x = x
x = (a, )
print(old_x is x)
# --> False, as old_x and x are not the same object (identity-wise)
print(old_x == x)
# --> True, as old_x and x are equal
在Python中,变量是弱类型的,这意味着,您可以自由地重新分配任何类型的变量。 在示例中,我们可以将字符串
"Hi World"
分配给 x
。