文章目录
- Python 中的可变对象与不可变对象
- 不可变对象(Immutable Objects)
- 可变对象(Mutable Objects)
- 重要区别
Python 中的可变对象与不可变对象
在 Python 中,对象可以分为可变对象(mutable)和不可变对象(immutable),这是 Python 中非常重要的概念,影响着对象的赋值、传递和修改行为。
不可变对象(Immutable Objects)
不可变对象是指创建后不能被修改的对象。如果尝试修改,实际上是创建了一个新对象。
常见的不可变类型:
- 数字类型:
int
,float
,bool
- 字符串:
str
- 元组:
tuple
- 冻结集合:
frozenset
示例:
# 整数是不可变的
x = 10
print(id(x)) # 打印内存地址
x += 1
print(id(x)) # 内存地址改变,是新对象# 字符串是不可变的
s = "hello"
print(id(s))
s += " world"
print(id(s)) # 新字符串对象# 元组是不可变的
t = (1, 2, 3)
try:t[0] = 100 # 尝试修改元组的第一个元素
except TypeError as e:print(e) # 输出错误信息(TypeError)
特别注意:
尽管元组本身是不可变的,但如果元组中包含可变对象,如列表,这些可变对象内部的内容是可以被修改的。这种情况下,元组的不可变性只适用于顶层结构,不影响内部元素的可变性。
tup = (1, [2, 3], 4)
tup[1].append(5) # 修改元组中的列表
print(tup) # 输出 (1, [2, 3, 5], 4)
可变对象(Mutable Objects)
可变对象是指创建后可以被修改的对象,修改时内存地址不变。
常见的可变类型:
- 列表:
list
- 字典:
dict
- 集合:
set
- 字节数组:
bytearray
- 用户自定义的类实例
示例:
# 列表是可变的
lst = [1, 2, 3]
print(id(lst)) # 打印内存地址
lst.append(4)
print(id(lst)) # 内存地址不变# 字典是可变的
d = {'a': 1}
print(id(d))
d['b'] = 2
print(id(d)) # 内存地址不变# 集合是可变的
st = {1, 2, 3}
print(id(st))
st.add(4)
st.remove(3)
print(id(st))
重要区别
-
赋值与修改:
# 不可变对象 a = 1 b = a b = 2 # a不变# 可变对象 x = [1, 2] y = x y.append(3) # x也被修改
-
函数参数传递:
- 不可变对象作为参数时,函数内修改不会影响原值
- 可变对象作为参数时,函数内修改会影响原值
def modify(num, lst):num += 1lst.append(4)n = 10 l = [1, 2, 3] modify(n, l) print(n) # 输出10,不变 print(l) # 输出[1, 2, 3, 4],被修改
-
字典键的限制:
- 只有不可变对象可以作为字典的键
- 可变对象不能作为字典的键
d = {} d['key'] = 'value' # 字符串键,合法 d[1] = 'number' # 整数键,合法 d[(1, 2)] = 'tuple' # 元组键,合法# d[[1, 2]] = 'list' # 报错,列表不能作为键
-
集合元素的限制:
尽管集合是可变的,但也有一些操作上的限制。例如,集合只能包含不可变(可哈希)的对象。因此不能将列表或另一个集合作为元素添加到集合中。nested_set = {1, 2, 3} try:nested_set.add([4, 5, 6]) # 尝试添加列表到集合中# nested_set.add({7, 8, 9}) # 尝试添加另一个集合到集合中 except TypeError as e:print(e) # 输出错误信息
理解可变和不可变对象的区别对于编写正确、高效的 Python 代码非常重要,特别是在处理对象传递和共享状态时。