python中可变与不可变对象的核心区别在于能否原地修改(id不变):不可变对象(如int、str、tuple)任何“修改”都生成新对象;可变对象(如list、dict)可通过方法直接修改自身内容且id不变,影响函数传参、字典键等场景。

Python 中可变对象与不可变对象的核心区别在于:对象创建后,其内存中的值能否被原地修改(即不改变 id 的前提下修改内容)。这是面试高频考点,关键不在背定义,而在理解行为差异及其对函数传参、赋值、字典键等场景的实际影响。
一、本质区别:是否支持“原地修改”
不可变对象(如 int、str、tuple)一旦创建,内容无法更改。任何看似“修改”的操作(如 s += "x" 或 i += 1)实际是创建新对象,并让变量指向它——原对象未变,id 必然不同。
可变对象(如 list、dict、set)允许通过方法(如 .append()、.update())直接修改自身内容,id 保持不变。
二、典型表现:赋值与修改的对比
以下代码直观体现差异:
本文档主要讲述的是Python之模块学习;python是由一系列的模块组成的,每个模块就是一个py为后缀的文件,同时模块也是一个命名空间,从而避免了变量名称冲突的问题。模块我们就可以理解为lib库,如果需要使用某个模块中的函数或对象,则要导入这个模块才可以使用,除了系统默认的模块(内置函数)不需要导入外。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
# 不可变对象:a 和 b 指向同一对象 → 但修改 a 会断开关联
a = 5<br>b = a<br>print(id(a) == id(b)) # True<br>a += 1 # 实际是 a = a + 1,生成新 int 对象<br>print(a, b) # 6, 5<br>print(id(a) == id(b)) # False
立即学习“Python免费学习笔记(深入)”;
# 可变对象:a 和 b 指向同一对象 → 修改 a 也影响 b
a = [1, 2]<br>b = a<br>print(id(a) == id(b)) # True<br>a.append(3)<br>print(a, b) # [1, 2, 3], [1, 2, 3]<br>print(id(a) == id(b)) # True
三、关键影响场景
- 函数参数传递:Python 是“对象引用传递”。传入可变对象时,函数内修改会影响外部原对象;传入不可变对象时,修改只会作用于局部变量。
-
作为字典的键:只有不可变对象能当 dict key(因为 key 需哈希且不能变),所以
{[1]: "a"}报错,而{(1,): "a"}合法。 -
浅拷贝 vs 深拷贝:对可变对象,
copy.copy()只复制外层,嵌套的可变对象仍共享;copy.deepcopy()才彻底隔离。不可变对象无需深拷贝。
四、常见误区提醒
- “字符串拼接慢”不是因为 str 不可变,而是每次拼接都新建对象,时间复杂度高;用
''.join(list)更高效。 - 元组(tuple)不可变,是指其元素引用不可变,不是元素内容不可变。例如
t = ([1], 2),t[0].append(3)合法(修改了列表),但t[0] = [4]报错(试图替换元组中元素)。 - 自定义类默认是可变的(除非实现
__slots__或冻结逻辑),与内置类型性质无关。









