✅ **Python 中的类(Class)、继承(Inheritance)与多态(Polymorphism)是面向对象编程(OOP)的三大基石**。它们共同支撑起可复用、可扩展、易维护的代码结构。下面以**概念本质 → 语法实现 → 运行机制 → 工程范式 → 常见误区**为脉络,系统、深入、可验证地讲解,并附**全部可直接运行的 Python 代码**。
---
### 🔹 一、类(Class):封装 + 模板 + 命名空间
#### ✅ 定义
类是创建对象的蓝图(blueprint),它将**数据(属性)** 和**行为(方法)** 封装在一起,形成逻辑单元;同时提供命名空间隔离和实例化能力。
#### ✅ 最小完整示例
```python
class Person:
species = "Homo sapiens" # ✅ 类属性(所有实例共享)
def __init__(self, name: str, age: int):
self.name = name # ✅ 实例属性(每个对象独有)
self.age = age
def greet(self) -> str: # ✅ 实例方法(第一个参数必须是 self)
return f"Hello, I'm {self.name} and {self.age} years old."
@classmethod
def get_species(cls) -> str: # ✅ 类方法(第一个参数是 cls)
return cls.species
@staticmethod
def is_adult(age: int) -> bool: # ✅ 静态方法(无隐式参数)
return age >= 18
# ✅ 实例化与使用
p1 = Person("Alice", 30)
p2 = Person("Bob", 16)
print(p1.greet()) # Hello, I'm Alice and 30 years old.
print(Person.get_species()) # Homo sapiens
print(Person.is_adult(25)) # True
```
#### ✅ 关键特性速查表:
| 特性 | 说明 | 示例 |
|------|------|------|
| `__init__` | 构造方法,创建实例时自动调用 | `p = Person("X", 20)` 触发 |
| `self` | 指向当前实例的引用(非关键字,但约定俗成) | `def greet(self): ...` |
| 类属性 vs 实例属性 | 类属性属于类本身(共享);实例属性属于每个对象(独立) | `Person.species` 共享;`p1.name` 独立 |
| `@classmethod` | 绑定到类,常用于替代构造器(如 `from_string()`) | `@classmethod def from_json(cls, s): ...` |
| `@staticmethod` | 独立函数,仅逻辑上属于类,不访问 `self`/`cls` | `@staticmethod def validate_email(s): ...` |
> 💡 **本质洞察**:Python 的类本质上是**可调用的对象(type 的实例)**,其定义过程会动态创建 `type` 对象,`class Person:` 等价于 `Person = type('Person', (), {...})`。
---
### 🔹 二、继承(Inheritance):is-a 关系 + 代码复用
#### ✅ 定义
子类自动获得父类的**所有可访问属性和方法**,并可选择性重写(override)或扩展,体现“**是一种**”(is-a)关系(如 `Dog` is a `Animal`)。
#### ✅ 单继承 + `super()` 正确用法(推荐!)
```python
class Animal:
def __init__(self, name: str):
self.name = name
def make_sound(self) -> str:
return "Some sound"
class Dog(Animal): # ← 继承 Animal
def __init__(self, name: str, breed: str):
super().__init__(name) # ✅ 调用父类 __init__(推荐!)
self.breed = breed
def make_sound(self) -> str: # ✅ 方法重写(Override)
return f"{self.name} barks: Woof!"
# ✅ 使用
dog = Dog("Rex", "German Shepherd")
print(dog.name) # Rex(继承自 Animal)
print(dog.breed) # German Shepherd(Dog 自有)
print(dog.make_sound()) # Rex barks: Woof!(重写后的行为)
```
#### ✅ 多重继承与 MRO(Method Resolution Order)
```python
class A:
def method(self):
print("A.method")
class B(A):
def method(self):
print("B.method")
super().method() # ← 调用 MRO 中下一个(即 A)
class C(A):
def method(self):
print("C.method")
super().method()
class D(B, C):
pass
# ✅ 查看 MRO(决定 super() 调用顺序)
print(D.mro())
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
d = D()
d.method()
# 输出:
# B.method
# C.method
# A.method
```
> ✅ `super()` 不是“调用父类”,而是“调用 MRO 中下一个类的方法”——这是多重继承正确协作的关键!
---
### 🔹 三、多态(Polymorphism):同一接口,多种行为
#### ✅ 定义
**多态 = 接口统一 + 行为分离**:函数/方法接收父类类型(或协议)参数,但实际执行子类的具体实现。Python 通过**动态分派(dynamic dispatch)** 在运行时自动完成绑定。
#### ✅ 基于继承的多态(最清晰、最推荐)
```python
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self) -> float:
pass
class Rectangle(Shape):
def __init__(self, w: float, h: float):
self.w, self.h = w, h
def area(self) -> float:
return self.w * self.h
class Circle(Shape):
def __init__(self, r: float):
self.r = r
def area(self) -> float:
return 3.14159 * self.r ** 2
# ✅ 多态函数:只依赖 Shape 接口,不关心具体类型
def total_area(shapes: list[Shape]) -> float:
return sum(s.area() for s in shapes)
# ✅ 传入不同子类实例,自动调用各自 area()
shapes = [Rectangle(2, 3), Circle(1)]
print(total_area(shapes)) # 6.0 + 3.14159 ≈ 9.14159
```
#### ✅ 鸭子类型(Duck Typing):Python 的天然多态
```python
class Triangle:
def __init__(self, b, h):
self.b, self.h = b, h
def area(self): # ← 只要有 area() 方法,就可被 total_area 接受!
return 0.5 * self.b * self.h
# ✅ 无需继承 Shape,也能工作(鸭子类型)
tri = Triangle(4, 5)
print(total_area([Rectangle(1,1), tri])) # 1.0 + 10.0 = 11.0
```
> ✅ **关键结论**:Python 的多态不强制继承,但**继承 + 抽象基类(ABC)能提供设计契约、IDE 支持和类型检查保障**,是工程首选。
---
### 🔹 四、三者协同:一个真实场景(银行账户系统)
```python
from abc import ABC, abstractmethod
from decimal import Decimal
class Account(ABC):
def __init__(self, account_number: str, balance: Decimal = Decimal('0')):
self.account_number = account_number
self._balance = balance # ✅ 受保护属性(约定 _ 开头)
@property
def balance(self) -> Decimal:
return self._balance
@abstractmethod
def withdraw(self, amount: Decimal) -> bool:
pass
def deposit(self, amount: Decimal) -> None:
if amount > 0:
self._balance += amount
class SavingsAccount(Account):
def __init__(self, account_number: str, balance: Decimal = Decimal('0'), interest_rate: float = 0.02):
super().__init__(account_number, balance)
self.interest_rate = interest_rate
def withdraw(self, amount: Decimal) -> bool:
if self._balance >= amount:
self._balance -= amount
return True
return False
class CheckingAccount(Account):
def __init__(self, account_number: str, balance: Decimal = Decimal('0'), overdraft_limit: Decimal = Decimal('100')):
super().__init__(account_number, balance)
self.overdraft_limit = overdraft_limit
def withdraw(self, amount: Decimal) -> bool:
if self._balance + self.overdraft_limit >= amount:
self._balance -= amount
return True
return False
# ✅ 多态应用:统一处理不同账户
def process_withdrawal(account: Account, amount: Decimal) -> str:
success = account.withdraw(amount)
status = "Success" if success else "Failed"
return f"Withdraw {amount} from {account.account_number}: {status}"
# ✅ 创建不同子类实例
savings = SavingsAccount("SA001", Decimal('1000'))
checking = CheckingAccount("CA001", Decimal('500'), Decimal('200'))
print(process_withdrawal(savings, Decimal('200'))) # Success
print(process_withdrawal(checking, Decimal('800'))) # Success(因透支)
```
✅ **这里体现了 OOP 三要素完美协同:**
- **类**:封装账户状态(`_balance`, `account_number`)和行为(`withdraw`, `deposit`);
- **继承**:`SavingsAccount` / `CheckingAccount` 复用 `Account` 的通用逻辑(如 `deposit`, `balance` property);
- **多态**:`process_withdrawal` 函数对任意 `Account` 子类都适用,无需修改即可支持新账户类型(如 `BusinessAccount`)。
---
### 🔹 五、常见误区与最佳实践(避坑指南)
| 陷阱 | 错误代码 | 正确做法 | 原因 |
|--------|------------|----------------|------|
| **误用类属性做实例状态** | ```python<br>class Counter:<br> count = 0<br> def inc(self): self.count += 1 # ❌ 创建了实例属性 count!<br>``` | `self.__class__.count += 1` 或用 `@classmethod` | `self.count += 1` 是 `self.count = self.count + 1`,先读 `self.count`(未定义 → 找类属性 `0`),再赋值给 `self.count`(新建实例属性) |
| **`super()` 在多重继承中硬编码父类名** | `Animal.__init__(self, name)` | `super().__init__(name)` | 硬编码破坏 MRO,导致钻石继承失效;`super()` 自动按 MRO 调用 |
| **认为 Python 有方法重载(Overload)** | ```python<br>def speak(self, volume): ...<br>def speak(self, times): ... # ❌ 后者覆盖前者<br>``` | 用 `*args`, `**kwargs`, `functools.singledispatch` 或类型提示联合 | Python 不支持传统重载,同名方法定义会覆盖前一个 |
| **忽略 `__slots__` 的内存优化价值** | 大量实例(如百万级)用默认 `__dict__` | `class Point: __slots__ = ('x', 'y')` | 默认每个实例带 `__dict__`(哈希表),内存开销大;`__slots__` 用固定属性元组,节省 40–50% 内存 |
✅ **工程黄金法则:**
> - **组合优于继承**(Has-a > Is-a);
> - **用 ABC 定义契约,用 Protocol 支持鸭子类型**;
> - **`super()` + `__init_subclass__` 是现代 Python 继承的标配**;
> - **多态的目标是:新增子类时,现有函数无需修改**(开闭原则)。
---
### ✅ 总结一句话:
> **类是封装的容器,继承是复用的桥梁,多态是扩展的钥匙;三者结合,让 Python 代码从“能跑”走向“好维护、易测试、可演进”的工程级质量。**
---