Python 可变对象与不可变对象 笔记

一、基础概念

1. 不可变对象(Immutable)

  • 定义:对象创建后,内存中的值无法直接修改
  • 修改本质:任何修改操作都会创建新对象,变量指向新内存地址
  • 特点:可哈希、线程安全、无副作用、函数传参不影响原值

2. 可变对象(Mutable)

  • 定义:对象创建后,内存中的值可直接修改
  • 修改本质:不创建新对象,原内存地址不变
  • 特点:不可哈希、非线程安全、可能产生副作用、修改效率高

二、完整分类清单

✅ 不可变对象(值不能改)

  1. 数字类型:int(整数)、float(浮点数)、complex(复数)、bool(布尔)
  2. 序列类型:str(字符串)、tuple(元组)、bytes(字节串)
  3. 集合类型:frozenset(冻结集合)

✅ 可变对象(值可直接改)

  1. 序列类型:list(列表)、bytearray(字节数组)
  2. 映射类型:dict(字典)
  3. 集合类型:set(集合)
  4. 自定义类实例:所有自定义对象默认可变

三、核心对比表

对比维度不可变对象可变对象
修改方式新建对象,地址改变原地修改,地址不变
哈希性可哈希(可做字典键/集合元素)不可哈希(不能做字典键)
函数传参不修改外部原值会修改外部原值
性能创建/修改开销大增删改效率高
安全性高,无意外修改低,易产生副作用

四、代码示例

1. 不可变对象演示

# 整数(不可变)
a = 10
print(id(a))  # 原地址
a += 1        # 新建对象
print(id(a))  # 地址改变

# 字符串(不可变)
s = "hello"
# s[0] = "H"  # 直接报错
s_new = s.replace("h","H")  # 生成新字符串
print(s)      # 原值不变:hello

# 元组(不可变)
t = (1,2,[3,4])
# t[0] = 10   # 报错
t[2].append(5)# 可行:修改内部可变对象

2. 可变对象演示

# 列表(可变)
lst = [1,2,3]
print(id(lst)) # 原地址
lst.append(4)  # 原地修改
print(id(lst)) # 地址不变

# 字典(可变)
d = {"name":"Tom"}
d["age"] = 20  # 直接修改

# 共享副作用
a = [1,2]
b = a
b.append(3)
print(a) # [1,2,3] 原值被修改

五、高频考点 & 避坑指南

1. 元组特殊点

  • 元组本身不可变,但内部的可变元素(列表/字典)可以修改
  • 元组仅限制「元素引用」不可替换,不限制元素内容

2. 函数默认参数陷阱

# 错误写法(可变对象做默认参数)
def func(lst=[]):
    lst.append(1)
    return lst

# 正确写法
def func(lst=None):
    if lst is None:
        lst = []
    lst.append(1)
    return lst

3. 快速判断口诀

数串元组冻集合,不可变;列表字典集自定义,皆可变


六、总结

  1. 不可变int/str/tuple/frozenset → 值不可改,改则建新对象,安全
  2. 可变list/dict/set/bytearray/自定义对象 → 原地修改,地址不变
  3. 核心判断:修改后内存地址是否变化
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐