Skip to main content

Python 不可变(Immutable)对象与变量传递机制详解

· 3 min read

一、Python 不可变(Immutable)对象

1. 不可变对象类型

Python 中的不可变对象包括:

  • 数字类型:int, float, bool, complex
  • 字符串:str
  • 元组:tuple
  • 冻结集合:frozenset
  • bytes

2. 不可变特性表现

a = 10
b = a
a = 20 # 创建新对象,而不是修改原有对象
print(b) # 输出10,b不受a改变影响

s = "hello"
s[0] = "H" # 报错:TypeError,字符串不可变

3. 不可变对象的内存机制

a = 256
b = 256
print(a is b) # True,小整数池优化

c = 257
d = 257
print(c is d) # False,大整数不共享

二、可变(Mutable)对象

1. 可变对象类型

  • 列表:list
  • 字典:dict
  • 集合:set
  • 字节数组:bytearray
  • 自定义类对象

2. 可变特性表现

lst1 = [1, 2, 3]
lst2 = lst1
lst1.append(4)
print(lst2) # [1, 2, 3, 4],lst2也被修改

三、Python 变量传递机制

1. 按对象引用传递

Python 中所有参数传递都是按对象引用传递,但效果取决于对象类型:

  • 不可变对象:函数内修改会创建新对象,不影响原始值
  • 可变对象:函数内修改会影响原始对象

2. 函数参数传递示例

(1) 传递不可变对象

def modify_num(x):
x = x + 10
print("函数内x:", x) # 15

num = 5
modify_num(num)
print("原始num:", num) # 5(未改变)

(2) 传递可变对象

def modify_list(lst):
lst.append(4)
print("函数内lst:", lst) # [1, 2, 3, 4]

my_list = [1, 2, 3]
modify_list(my_list)
print("原始my_list:", my_list) # [1, 2, 3, 4](已改变)

3. 避免意外修改的解决方案

(1) 使用不可变对象

def safe_func(t):
t = t + (4,) # 创建新元组
print(t) # (1, 2, 3, 4)

orig_tuple = (1, 2, 3)
safe_func(orig_tuple)
print(orig_tuple) # (1, 2, 3)

(2) 创建副本

def safe_modify(lst):
lst_copy = lst.copy() # 或 list(lst) 或 lst[:]
lst_copy.append(4)
print("副本:", lst_copy) # [1, 2, 3, 4]

original = [1, 2, 3]
safe_modify(original)
print("原始:", original) # [1, 2, 3]

四、高级主题:深浅拷贝

特性浅拷贝 (Shallow Copy)深拷贝 (Deep Copy)
复制深度只复制最外层容器,内部元素保持引用关系递归复制所有嵌套对象,创建完全独立的新对象
内存占用较少较多
执行速度较快较慢
适用场景简单对象或明确不需要嵌套复制的情况复杂嵌套对象需要完全独立的情况
修改影响修改嵌套对象会影响原对象修改任何级别都不会影响原对象

1. 浅拷贝(shallow copy)

import copy

lst1 = [1, [2, 3], 4]
lst2 = copy.copy(lst1)

lst1[1][0] = 99
print(lst2) # [1, [99, 3], 4] 嵌套对象被修改

2. 深拷贝(deep copy)

import copy

lst1 = [1, [2, 3], 4]
lst2 = copy.deepcopy(lst1)

lst1[1][0] = 99
print(lst2) # [1, [2, 3], 4] 完全独立

五、实际应用建议

  1. API 设计:如果函数不应修改传入的可变参数,应在文档中明确说明
  2. 线程安全:不可变对象天然线程安全
  3. 字典键:只能使用不可变对象作为字典键
  4. 性能考虑:频繁修改字符串应考虑使用listbytearray