📄 一句话概括
实测三步:改类变量两个都变、给 u1 单独赋值只变 u1——读的时候顺着链找,写的时候只写自己那层。
📝 本节和前面几节的关系
4.6 看到 made 与 no 的差别,这一节把这句话讲成一条能用的规则。
一、这句话在说什么
实例变量像全局变量一样【谁都能用】——只要拿到那个对象。 但它的范围只到那个对象为止,不像模块级全局那样全文件都能碰。 所以准确说法是:它是【把全局变量的作用范围缩小到一个对象】。 范围一缩,3.9 说的干扰面就跟着缩。
二、实测三步
初始:User.role = 普通,u1.role 和 u2.role 都是普通。
改类变量 User.role = 管理员 之后:两个都变成管理员。
再给 u1.role = 访客 之后:只有 u1 变,u2 还是管理员。
读的时候顺着链找(实例 → 类),写的时候只写自己那层。
三、为什么第三步会【造出】一个实例变量
u1.role = 访客 看着像【改】,其实是在 u1 上新建了一个实例变量,把类的那个盖住了。
这一步之后,u1 有自己的 role,u2 没有——它们不再看同一个地方。
这就是【写只写自己那层】的具体机制。知道这一点,就不会困惑于【为什么改类变量没影响它】。
四、接回 3.9 的 480 条边
三个范围排一排:模块级全局(整个文件)→ 类变量(这个类)→ 实例变量(这一个对象)。 越往下,范围越小,干扰面越小。 480 条依赖边之所以可怕,是因为全局变量谁都能改;实例变量把那 480 条边断成一个个小圈子。 这就是 OOP 治【数据被谁改】这个病的具体手法。
五、动手 Demo:实例变量是限定访问范围的全局变量
三步走:改类变量、再给一个实例单独赋值。 看每一步有几个实例受影响。
class User:
role = "普通" # 类变量
def __init__(self, name):
self.name = name
u1, u2 = User("甲"), User("乙")
print(u1.role, u2.role) # 都看类变量
User.role = "管理员"
print(u1.role, u2.role) # 两个都变
u1.role = "访客" # 在 u1 上新建实例变量
print(u1.role, u2.role) # 只有 u1 变
实跑输出:
--------------------------------------------------------------------
实例变量是限定访问范围的全局变量
--------------------------------------------------------------------
这句话有点绕,但它是理解【实例之间互不影响】的钥匙。
**实例变量像全局变量一样【谁都能用】,但它只对自己那个类有效。**
u1 = User("甲"); u2 = User("乙")
初始:u1.role = 普通,u2.role = 普通
改类变量 User.role = 管理员 之后:
u1.role = 管理员,u2.role = 管理员 ← 两个都变了
再给 u1 单独赋值 u1.role = 访客:
u1.role = 访客,u2.role = 管理员 ← 只有 u1 变
实测这三步说明一件事:**读的时候顺着链找(实例 → 类),写的时候只写自己那层。**
位置 像不像全局变量 范围
---------------------------------------------
模块级全局 是 整个文件
类变量 是 这个类
实例变量 是 这一个实例
**所以小标题这句话的准确意思是:实例变量是【把全局变量的范围缩小到一个对象】。**
**范围一缩,3.9 说的 480 条依赖边就断成了一个个小圈子。**
实测三步:都普通 → 都管理员 → 只有 u1 变访客。 读的时候顺着链找(实例 → 类),写的时候只写自己那层——第二步的赋值其实是新建了一个实例变量。
30 秒实验
- 写一个带类变量的类,分别改类变量和改实例属性,观察影响范围。
- 找出你项目里被到处改的全局状态,看看能不能缩进某个对象。
常见误区
- 以为实例变量就是全局变量。范围只到那个对象。
- 以为给实例赋值是改类变量。那是在实例上新建一个,把类的盖住。
自测三问(点开对答案)
1. 实例变量像全局变量在哪、不像在哪? —— 像在【谁都能用】(拿到对象就行);不像在范围只到那一个对象,不是整个文件。 2. 给 u1.role 赋值时发生了什么? —— 在 u1 上新建了一个实例变量,把类变量盖住;u2 没有,所以只有 u1 变。 3. 这条性质怎么帮到 3.9 的 480 条依赖边? —— 范围从整个文件缩到一个对象,干扰面跟着缩——480 条边被断成一个个小圈子。- ☐ 下一节(4.8 三大要素之二:实现调用端公用化的多态)
相关笔记
- 类的功能之三:创建很多个 — 类变量与实例变量的分水岭
- 没有解决全局变量问题和可重用性差的问题 — 480 条依赖边
- 类指类型,实例指具体的物 — 实例到底是什么
- 🧩 面向对象是怎样工作的 · 索引