Python 抽象类
最后修改于 2025 年 3 月 25 日
Python 中的抽象类是不能被实例化的类,它们被设计为供其他类继承。它们充当其他类的蓝图,定义了子类必须实现的通用接口。Python 提供了 abc
模块来处理抽象基类 (ABC)。
当你想为一组相关类定义一个通用 API,同时强制要求在子类中实现某些方法时,抽象类尤其有用。它们通过明确定义子类应该实现的方法,帮助创建更易于维护和可预测的代码。@abstractmethod
装饰器标记了必须在具体子类中被重写的方法。
创建基本抽象类
此示例演示了如何在 Python 中创建和使用简单的抽象类。
from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def area(self): pass @abstractmethod def perimeter(self): pass class Rectangle(Shape): def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height def perimeter(self): return 2 * (self.width + self.height) rect = Rectangle(5, 10) print(rect.area()) # Output: 50 print(rect.perimeter()) # Output: 30 # shape = Shape() # Raises TypeError
Shape
类是一个抽象基类,它定义了两个抽象方法:area
和 perimeter
。像 Rectangle
这样的任何具体子类都必须实现这些方法。尝试直接实例化抽象类会引发 TypeError
。
抽象属性
此示例展示了如何在抽象类中定义抽象属性。
from abc import ABC, abstractmethod class Person(ABC): @property @abstractmethod def name(self): pass @abstractmethod def speak(self): pass class Employee(Person): def __init__(self, first_name, last_name): self._name = f"{first_name} {last_name}" @property def name(self): return self._name def speak(self): return f"Hello, my name is {self.name}" emp = Employee("John", "Doe") print(emp.name) # Output: John Doe print(emp.speak()) # Output: Hello, my name is John Doe
抽象属性将 @property
装饰器与 @abstractmethod
结合使用,要求具体子类实现特定的属性。在此示例中,Employee
类实现了抽象的 name
属性和抽象的 speak
方法。
带具体方法的抽象类
此示例演示了一个包含抽象方法和具体方法的抽象类。
from abc import ABC, abstractmethod class Database(ABC): @abstractmethod def connect(self): pass @abstractmethod def query(self, sql): pass def execute(self, sql): conn = self.connect() result = self.query(sql) conn.close() return result class MySQLDatabase(Database): def connect(self): print("Connecting to MySQL database") return "mysql_connection" def query(self, sql): print(f"Executing MySQL query: {sql}") return "query_results" db = MySQLDatabase() db.execute("SELECT * FROM users")
抽象类可以包含子类必须实现的抽象方法,也可以包含提供共享功能的具体方法。在此示例中,execute
方法在抽象类中已完全实现,但它依赖于子类必须提供的抽象方法 connect
和 query
。
注册虚拟子类
此示例展示了如何将类注册为抽象基类的虚拟子类,而无需显式继承。
from abc import ABC, abstractmethod class Animal(ABC): @abstractmethod def make_sound(self): pass class Dog: def make_sound(self): return "Woof!" Animal.register(Dog) # Register Dog as virtual subclass dog = Dog() print(isinstance(dog, Animal)) # Output: True print(issubclass(Dog, Animal)) # Output: True print(dog.make_sound()) # Output: Woof!
register
方法允许你声明一个类实现了抽象基类,而无需显式继承它。注册的类必须实现所有抽象方法,但这要到你尝试使用这些方法时才会进行检查。这在处理无法修改的类或使用鸭子类型时很有用。
带类方法的抽象类
此示例演示了在抽象基类中使用抽象类方法。
from abc import ABC, abstractmethod class Serializer(ABC): @classmethod @abstractmethod def serialize(cls, data): pass @classmethod @abstractmethod def deserialize(cls, serialized_data): pass class JSONSerializer(Serializer): @classmethod def serialize(cls, data): return f"JSON: {data}" @classmethod def deserialize(cls, serialized_data): return serialized_data.replace("JSON: ", "") print(JSONSerializer.serialize({"key": "value"})) # Output: JSON: {'key': 'value'}
抽象类方法使用 @classmethod
和 @abstractmethod
装饰器进行定义。子类必须实现这些类方法。当你想在相关类之间强制执行类级别的 API 时,这种模式很有用,例如此示例中的不同序列化格式。
抽象类的多重继承
此示例展示了如何在多重继承中使用抽象类。
from abc import ABC, abstractmethod class Readable(ABC): @abstractmethod def read(self): pass class Writable(ABC): @abstractmethod def write(self, data): pass class ReadWriteFile(Readable, Writable): def __init__(self, filename): self.filename = filename def read(self): return f"Reading from {self.filename}" def write(self, data): return f"Writing '{data}' to {self.filename}" file = ReadWriteFile("example.txt") print(file.read()) # Output: Reading from example.txt print(file.write("Hello")) # Output: Writing 'Hello' to example.txt
抽象类可以通过多重继承组合起来,创建实现多个接口的类。ReadWriteFile
类继承自 Readable
和 Writable
抽象类,并实现了它们的所有抽象方法。这种方法允许灵活的接口定义,同时保持严格的实现要求。
抽象类的最佳实践
- 用于 API 定义:抽象类非常适合定义子类必须实现的清晰 API。
- 保持抽象方法最少:只有当方法对于类的目的真正必需时,才将其标记为抽象。
- 记录意图:清晰地记录方法为何是抽象的以及实现应该做什么。
- 偏好组合:考虑组合是否比继承更适合你的用例。
- 测试子类:验证子类是否正确实现了所有抽象方法。
来源
在本文中,我们探讨了 Python 抽象类,并通过实际示例展示了它们在面向对象设计中的用法。
作者
列出所有 Python 教程。