如何在Python中修改不可变变量的值?
·
Python 修改不可变变量的值:没有原地修改,只能重新赋值
先记住核心结论: 不可变对象(int/float/str/tuple/bool/frozenset)不能在原有内存地址上修改内部数据,想要改变变量存储的值,只能让变量名指向一个全新的对象。
一、什么叫重新赋值
旧对象保留在内存中,变量不再引用它,转而绑定新的值,内存地址会发生改变。
1. 整数 int 示例
python
运行
num = 10
print(id(num))
# 重新赋值,不是修改原来的10
num = 20
print(id(num)) # 地址改变,生成新对象
2. 字符串 str 示例
字符串没有任何原地修改方法,拼接、替换都会返回新字符串:
python
运行
s = "hello"
new_s = s + " world"
# 原字符串 s 没变,只是用新变量接收新字符串
# 如果要覆盖原变量名:
s = s.replace("hello", "hi")
3. 元组 tuple 示例
元组不能通过索引修改元素,只能拼接、切片生成新元组再赋值:
python
运行
t = (1, 2, 3)
# t[0] = 100 直接报错,无法原地修改
# 正确方式:生成新元组重新赋值
t = t + (4,)
print(t) # (1, 2, 3, 4)
4. 浮点数、布尔
python
运行
pi = 3.14
pi = 3.14159
flag = True
flag = False
5. 不可变集合 frozenset
只能创建新集合再赋值:
python
运行
fs = frozenset({1,2})
# fs.add(3) 报错
fs = frozenset({1,2,3})
二、常见误区:不是原地修改,只是换了个新对象
python
运行
a = "abc"
a += "d"
很多人以为这是修改字符串,本质:
- 先创建新字符串
abcd - 变量
a放弃原来abc的引用,指向新字符串 - 旧的
abc字符串不会被改动,等待垃圾回收
三、如果一定要 “原地可变” 怎么办?两种方案
方案 1:用可变类型包裹不可变数据
把数字、字符串放到列表里,通过列表原地修改:
python
运行
num = [10]
num[0] = 20 # 列表可变,原地修改包裹的数据
方案 2:使用 nonlocal / global 修改变量作用域绑定
不是修改对象本身,而是修改变量名绑定的值:
python
运行
count = 0
def add():
global count
count += 1 # 本质:count = count + 1,重新绑定新int对象
四、易错补充:元组内含可变元素可以改内部数据
python
运行
t = (1, [2, 3])
t[1].append(4)
这里并没有修改元组本身,只是修改了元组内部的列表(可变对象),元组里存储的列表内存地址没有变,不属于修改不可变类型。
总结
- 不可变类型无法原地修改,只能通过重新赋值让变量指向新对象;
- 字符串、元组的拼接、替换、切片操作,都会返回全新对象;
- 想要实现原地修改效果,可以用列表等可变容器包裹不可变数据;
global、nonlocal只是修改变量绑定关系,不是修改原始不可变对象。
需要分别整理字符串、元组常用生成新对象的方法清单吗?
所有评论(0)