Python 抽象基类 ABC
abc 模块提供抽象基类机制,强制子类实现特定方法,确保接口一致性。
基本用法
Python
from abc import ABC, abstractmethod
class Animal(ABC):
"抽象基类"
@abstractmethod
def speak(self):
"子类必须实现"
pass
@abstractmethod
def move(self):
"子类必须实现"
pass
class Dog(Animal):
def speak(self):
return "汪汪"
def move(self):
return "跑"
class Cat(Animal):
def speak(self):
return "喵喵"
def move(self):
return "跳"
# 实例化子类
dog = Dog()
print(dog.speak()) # 汪汪
# 实例化抽象类会报错
# Animal() # TypeError: Can't instantiate abstract class Animal
未实现抽象方法的错误
Python
class Bird(Animal):
def speak(self):
return "啾啾"
# 未实现 move 方法
# Bird() # TypeError: Can't instantiate abstract class Bird with abstract method 'move'
抽象属性
Python
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@property
@abstractmethod
def name(self):
"抽象属性"
pass
class Circle(Shape):
def __init__(self, radius):
self._radius = radius
def area(self):
return 3.14 * self._radius ** 2
@property
def name(self):
return "圆形"
c = Circle(5)
print(c.area()) # 78.5
print(c.name) # 圆形
抽象类方法与静态方法
Python
from abc import ABC, abstractmethod
class Plugin(ABC):
@classmethod
@abstractmethod
def create(cls):
"抽象类方法"
pass
@staticmethod
@abstractmethod
def info():
"抽象静态方法"
pass
class MyPlugin(Plugin):
@classmethod
def create(cls):
return cls()
@staticmethod
def info():
return "MyPlugin v1.0"
p = MyPlugin.create()
print(MyPlugin.info()) # MyPlugin v1.0
装饰器顺序:
@classmethod/@staticmethod必须在最外层。
注册虚拟子类
使用 register 将类注册为抽象基类的虚拟子类:
Python
from abc import ABC, abstractmethod
class MySequence(ABC):
@abstractmethod
def __getitem__(self, index):
pass
@abstractmethod
def __len__(self):
pass
# 注册内置类型为虚拟子类
MySequence.register(list)
MySequence.register(tuple)
# 类型检查生效
print(isinstance([1, 2, 3], MySequence)) # True
print(isinstance((1, 2), MySequence)) # True
subclasshook 自定义检查
Python
from abc import ABC
class ContainerLike(ABC):
"自定义子类检查"
@classmethod
def __subclasshook__(cls, subclass):
# 检查是否有 __contains__ 方法
if hasattr(subclass, '__contains__'):
return True
return NotImplemented
# 不继承但符合协议
class MyContainer:
def __contains__(self, item):
return True
print(isinstance(MyContainer(), ContainerLike)) # True
collections.abc 模块
Python 内置多种抽象基类:
Python
from collections.abc import Sized, Iterable, Container, Sequence
# Sized:有 __len__ 方法
class MyList(Sized):
def __init__(self, data):
self.data = data
def __len__(self):
return len(self.data)
lst = MyList([1, 2, 3])
print(isinstance(lst, Sized)) # True
print(len(lst)) # 3
# 检查内置类型
print(isinstance([1, 2], Sized)) # True
print(isinstance("hello", Iterable)) # True
print(isinstance({1, 2}, Container)) # True
print(isinstance((1, 2), Sequence)) # True
常用抽象基类
| 基类 | 要求方法 |
|---|---|
Sized | __len__ |
Iterable | __iter__ |
Container | __contains__ |
Sequence | __getitem__, __len__ |
Mapping | __getitem__, __iter__, __len__ |
Set | __contains__, __iter__, __len__ |
接口继承示例
Python
from abc import ABC, abstractmethod
class Database(ABC):
"数据库接口"
@abstractmethod
def connect(self):
pass
@abstractmethod
def disconnect(self):
pass
@abstractmethod
def execute(self, query):
pass
@abstractmethod
def fetch(self):
pass
class MySQLDatabase(Database):
def connect(self):
print("连接 MySQL")
def disconnect(self):
print("断开 MySQL")
def execute(self, query):
print(f"执行: {query}")
def fetch(self):
return ["row1", "row2"]
class PostgreSQLDatabase(Database):
def connect(self):
print("连接 PostgreSQL")
def disconnect(self):
print("断开 PostgreSQL")
def execute(self, query):
print(f"执行: {query}")
def fetch(self):
return ["row1", "row2"]
# 统一接口调用
def use_database(db: Database):
db.connect()
db.execute("SELECT * FROM users")
print(db.fetch())
db.disconnect()
use_database(MySQLDatabase())
use_database(PostgreSQLDatabase())
抽象基类与鸭子类型
Python
# 鸭子类型:只要有方法就能用
class DuckTyped:
def speak(self):
return "叫声"
def make_sound(animal):
# 不检查类型,直接调用
return animal.speak()
make_sound(DuckTyped()) # 声
# 抽象基类:强制接口
def make_sound_with_abc(animal: Animal):
# 类型检查确保有 speak 方法
return animal.speak()
make_sound_with_abc(Dog()) # 汪汪
# make_sound_with_abc(DuckTyped()) # DuckTyped 不是 Animal 子类
| 方式 | 特点 |
|---|---|
| 鸭子类型 | 不需要继承,灵活但无约束 |
| 抽象基类 | 强制接口,有类型检查保障 |
混合使用抽象方法与普通方法
Python
from abc import ABC, abstractmethod
class Vehicle(ABC):
"抽象基类可以有普通方法"
@abstractmethod
def start(self):
pass
@abstractmethod
def stop(self):
pass
def horn(self):
"普通方法:所有子类共享"
return "鸣笛"
class Car(Vehicle):
def start(self):
print("启动汽车")
def stop(self):
print("停止汽车")
car = Car()
car.start()
car.horn() # 鸣笛(继承普通方法)
要点总结
| 要点 | 说明 |
|---|---|
ABC | 抽象基类父类 |
@abstractmethod | 定义抽象方法 |
| 实例化限制 | 未实现所有抽象方法无法实例化 |
register() | 注册虚拟子类 |
__subclasshook__ | 自定义类型检查逻辑 |
抽象基类提供接口约束,与鸭子类型互补,适合需要类型检查和强制接口的场景。
D:\git2\jwdev\articles\PYTHON\进阶\面向对象编程\抽象基类ABC.md
📝 发现内容有误?点击此处直接编辑