📄 一句话概括
类是一份模板,实例是按模板做出来的物;状态相同不等于同一个物,而类自己也是一个对象。
📝 本节和前面几节的关系
2.1 把名词变成了类,这一节把【类】和【实例】分清——这是后面所有讨论的地基。
一、模板与物
类是模板:它规定有哪些字段、哪些方法。
实例是按模板做出来的一个一个具体的物:每个都有自己的字段值。
所以 Customer 是类,Customer("小林") 是实例。一份模板,可以做出无数个物。
二、字段一样,也不是同一个
造两个同名同电话的顾客:状态完全一样(a.name == b.name 是 True)。
但它们不是同一个物:a is b 是 False,a == b 也是 False。
为什么 == 也是 False?因为没写 __eq__ 时,== 默认比的也是身份。
这是很多人踩过的坑:以为内容一样就相等,其实默认比的是【是不是它】。
三、类本身也是对象
实测 type(Customer) 不是 Customer,而是 type。
也就是说,类本身是 type 的一个实例——所以类也能被传来传去、也能运行时动态创建。
这一条在很多语言里成立(Java 的 Class 对象、Python 的元类),只是不太常用。
四、这一对区分后面还会用到
5.8 讲【每次创建实例都会使用堆区】——说的就是实例。 5.7 讲【每个类只加载一个类信息】——说的就是类。 5.10 讲【复制存储实例的变量要小心】——根子就在【状态相同 ≠ 同一个物】。 所以这一节看着简单,其实是给第 5 章铺路。
五、动手 Demo:类指类型,实例指具体的物
造两个状态完全一样的实例,逐条对比身份与相等。 再看一眼类本身是什么类型的对象。
class Customer:
def __init__(self, name):
self.name = name
a = Customer("小林")
b = Customer("小林")
checks = [
("a.name == b.name", a.name == b.name),
("a is b", a is b),
("a == b", a == b),
("id(a) == id(b)", id(a) == id(b)),
("type(Customer).__name__", type(Customer).__name__),
("type(Customer) is type", type(Customer) is type),
]
for k, v in checks:
print(k, v)
实跑输出:
--------------------------------------------------------------------
类指类型,实例指具体的物
--------------------------------------------------------------------
【类】是一份模板,**【实例】是按模板做出来的一个一个具体的物。**
两个坑全在细节里,真跑一遍就看得见。
a = Customer("小林")
b = Customer("小林")
表达式 实测结果 说明了什么
----------------------------------------------------------------
a.name == b.name True 状态一样
a is b False 不是同一个物
a == b False 没写 __eq__,== 比身份
id(a) == id(b) False 地址不同
type(Customer).__name__ type 类也是对象
type(Customer) is type True 它是 type 的实例
**看第 1 行和第 3 行**:状态一样(True),却不是同一个物(False)。
而且 `==` 默认比的也是身份——**要按内容相等,得自己写 `__eq__`。**
**记住这一对区分:状态相同 ≠ 是同一个物。**
后面 5.10 讲【复制实例变量要小心】,根子就在这里。
实测:状态一样(True),a is b 和 a == b 都是 False。
== 默认比的也是身份——要按内容相等,得自己写 __eq__。
30 秒实验
- 给自己写的类加上
__eq__,看a == b会不会变 True。 - 打印
type(你的类),确认它也是type。
常见误区
- 以为字段值一样就是同一个对象。身份和状态是两回事。
- 以为
==比的是内容。没写__eq__时它比的是身份。
自测三问(点开对答案)
1. 类和实例分别是什么? —— 类是模板,规定有哪些字段和方法;实例是按模板做出来的具体的物,各有自己的字段值。 2. 两个字段完全一样的实例相等吗? —— 不一定。没写 __eq__ 时 == 比的是身份,所以两个独立实例既不 is 也不 ==。 3. 类本身是什么? —— 类也是对象——它是 type 的实例,所以能被传递、能在运行时动态创建。- ☐ 下一节(2.3 多态让消息的发送方法变得通用)
相关笔记
- 对照现实世界介绍面向对象 — 名词怎么变成类
- 复制存储实例的变量时要多加注意 — 这一对区分的正题
- ☕ Java基础 · 索引 — 对象与引用的语法细节
- 🧩 面向对象是怎样工作的 · 索引