基础篇 · Foundations
lv.1 入门
kp-003
变量与引用(名字绑定)
1. 一句话定义
Python 的变量不是"装值的盒子",而是指向对象的标签——赋值语句做的是"名字 → 对象"的绑定,而不是把值复制进去。
2. 为什么重要
这是 Python 第一块真正的"心智地基":它解释了赋值、参数传递、可变默认值、深浅拷贝等一大串行为的根源。理解错了,之后每个模块都会摔跤。
3. 前置知识
4. 核心概念
- 对象(object):内存中的一块数据,自带类型和身份(
id()返回的地址感标识)。 - 名字(name):指向对象的标签,存放在命名空间里。
- 赋值:
x = 10的含义是"把名字x绑定到整数对象 10",10 本身不变。 - 多个名字可指向同一对象:
y = x只复制了"标签",不复制对象。
5. 原理与机制
python
a = [1, 2]
b = a # b 与 a 指向同一个列表对象
b.append(3)
print(a) # [1, 2, 3] ← a 也"变"了,其实是同一个对象
x = 10
y = x
y = 20 # 给 y 重新绑定到新对象 20,x 不受影响
print(x) # 10规则:修改对象(b.append)对所有引用可见;重新绑定名字(y = 20)只影响这个名字。id()、is 运算符可验证身份(详见 kp-005、kp-028)。
6. 关键事实(模型/图示)
text
赋值前: a ──┐
├──► [1, 2] (同一个对象)
b = a 后: b ──┘
y = 20 后: y ──► 20 (新对象)
x ──► 10 (旧对象,未动)- 类型跟着对象走:名字本身没有类型,所以同一名字可先后绑定不同类型——这就是"动态类型"。
- 小整数(-5~256)等常见对象会被 CPython 缓存复用,属实现细节,不要依赖。
7. 直观类比
变量是便利贴,不是抽屉。同一件行李(对象)可以贴多张便利贴(多个名字);撕下一张贴到新行李上(重新绑定),不影响旧行李和其他便利贴。而"修改行李内容"(append),所有贴着它的人都看得见。
8. 实例与案例
函数参数传递就是名字绑定的重演(详见 kp-007 的"传引用/传值之争"小节):
python
def mutate(lst):
lst.append(99) # 修改对象 → 调用方看得见
def rebind(lst):
lst = [0] # 重新绑定局部名字 → 调用方看不见9. 常见误区
- "Python 传值/传引用"二选一的说法都不准确 —— 准确说法是"传对象引用的共享"(call by object reference)。
- 以为
b = a复制了列表 —— 只复制引用,复制列表要用a.copy()或list(a)(深浅拷贝见 kp-028)。 - 以为变量有类型 —— 对象才有类型;
type(x)查的是 x 当前绑定的对象。
10. 自测题
x = [1]; y = x; y = [2]后,x是什么?为什么?- 如何验证两个名字指向同一个对象?
- 为什么
def f(lst=[]): lst.append(1)是著名陷阱?(预告 kp-007)
参考答案
[1]。y = [2]是把 y 重新绑定到新对象,未修改原列表。x is y(身份比较)或比较id(x) == id(y)。- 默认值在函数定义时求值一次并绑定到该参数——所有不带该参数的调用共享同一个列表对象。
11. 与其他知识点的关系
12. 延伸阅读
- Fluent Python 第 6 章 "Variables Are Not Boxes"
- Python 官方教程 3.1 节