【Python】变量赋值与引用机制:探究对象的可变性
概述
在Python中,变量赋值的机制涉及到对象的引用和对象的可变性。变量名只是对象的引用,而不是直接存储数据。因此,变量a和b赋值后的行为差异,取决于两个因素:
- 对象是否可变(Mutable/Immutable)。
- 修改操作的类型(直接修改对象内容,还是重新赋值变量)。
1. 不可变对象(Immutable Objects)
不可变对象的值一旦创建,就不能修改其内容,例如:
int)str)tuple)bool)等。场景:修改变量的新赋值
a = 5 # a指向整数对象5
b = a # b也指向同一个整数对象5
a = 6 # 此时a指向新的整数对象6,但b仍指向5
print(b) # 输出5
原因:
b = a 时,仅复制引用,使得 a 和 b 都指向同一个对象(初始是5)。a = 6 时,a 的引用被更新为指向新对象6,而 b 仍然指向原对象5。b 不会变化。场景:尝试直接修改对象内容(无效)
a = "hello" # a指向字符串"hello"
b = a # b也指向相同的字符串对象
# 尝试修改字符串内容(但不可变对象不允许此操作)
a[0] = "H" # 报错:'str' object does not support item assignment
结果:此操作根本无法执行,因为字符串是不可变的。
2. 可变对象(Mutable Objects)
可变对象的值可以在创建后被修改,例如:
list)dict)set)场景:直接修改对象内容
a = [1, 2] # a指向列表[1, 2]
b = a # b指向同一个列表对象
a.append(3) # 修改列表内容,原列表变为[1, 2, 3]
print(b) # 输出[1, 2, 3]
原因:
a 和 b 指向同一个列表对象。append() 方法直接修改了该对象的内部内容,因此两个变量看到的都是同一个被修改后的对象。场景:修改变量的引用(不影响对方)
a = [1, 2]
b = a
a = [3, 4] # a的引用被更新为新列表[3,4],但b仍指向原列表[1,2]
print(b) # 输出[1, 2]
原因:
a = [3,4] 是一个新的赋值操作,直接改变了a的引用,使其指向新对象,而b未被修改,依然指向原列表。3. 核心总结
| 情况 | 行为差异原因 |
|---|---|
| 修改对象内容(可变对象) | a 和 b 指向同一个对象,修改内容会影响双方。 |
| 直接重新赋值变量(任何对象) | a 的引用指向新对象,而 b 的引用未变,因此 b 的值不受影响。 |
| 尝试修改不可变对象的内容 | 不可变对象无法被修改,只能生成新对象,原对象的引用不会改变。因此 b 不变。 |
4. 如何避免混淆
a,b 不变”,这是因为实际是生成了新对象。a,b 也变”,是因为两变量指向同一个对象,修改内容会影响双方。若希望二者独立:
import copy
b = copy.deepcopy(a) # 完全独立的副本
示例表格
| 示例代码 | 是否修改对象内容 | a 的值 |
b 的值 |
|---|---|---|---|
a = 5; b = a; a = 6 |
否 | 6 | 5 |
a = [1]; b = a; a[0] = 2 |
是(修改可变对象) | [2] |
[2] |
a = [1]; b = a; a = [2] |
否 | [2] |
[1] |
| `a = “str”; b = a; a += “1” | 否(生成新对象) | "str1" |
"str" |
关键点:
b = a 仅让两个变量指向同一个对象。作者:牛顿编程