Python 可变/不可变和局部变量

问题描述 投票:0回答:3

对以下两个代码片段的行为差异感到非常困惑,特别是对它们在 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
主体的赋值内部所采取的操作。

为什么有区别?这里发生了什么事?为什么元组的不可变性仅在第一个片段中显示?

python immutability
3个回答
0
投票
  1. 您正在修改对象 x 的现有行为,即元组
  2. 您覆盖现有对象并为其赋予新的定义/行为。

0
投票

这是一个示例,希望可以使其更容易理解:

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
指向该新对象。


0
投票

在您的示例中,

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

© www.soinside.com 2019 - 2024. All rights reserved.