ai
  • index
  • cursor
  • vector
  • crawl
  • crawl-front
  • DrissionPage
  • logging
  • mysql
  • pprint
  • sqlalchemy
  • contextmanager
  • dotenv
  • Flask
  • python
  • job
  • pdfplumber
  • python-docx
  • redbook
  • douyin
  • ffmpeg
  • json
  • numpy
  • opencv-python
  • pypinyin
  • re
  • requests
  • subprocess
  • time
  • uuid
  • watermark
  • milvus
  • pymilvus
  • search
  • Blueprint
  • flash
  • Jinja2
  • secure_filename
  • url_for
  • Werkzeug
  • chroma
  • HNSW
  • pillow
  • pandas
  • beautifulsoup4
  • langchain-community
  • langchain-core
  • langchain
  • langchain_unstructured
  • libreoffice
  • lxml
  • openpyxl
  • pymupdf
  • python-pptx
  • RAGFlow
  • tabulate
  • sentence_transformers
  • jsonl
  • collections
  • jieba
  • rag_optimize
  • rag
  • rank_bm25
  • Hugging_Face
  • modelscope
  • all-MiniLM-L6-v2
  • ollama
  • rag_measure
  • ragas
  • ASGI
  • FastAPI
  • FastChat
  • Jupyter
  • PyTorch
  • serper
  • uvicorn
  • markdownify
  • NormalizedLevenshtein
  • raq-action
  • CrossEncoder
  • Bi-Encoder
  • neo4j
  • neo4j4python
  • matplotlib
  • Plotly
  • Streamlit
  • py2neo
  • abc
  • read_csv
  • neo4jinstall
  • APOC
  • neo4jproject
  • uv
  • GDS
  • heapq
  • 1. 为什么需要抽象基类
  • 2. 基本用法
    • 2.1 创建抽象基类
    • 2.2 实现抽象基类
  • 3. 其他装饰器
    • 3.1 @abstractclassmethod
    • 3.2 @abstractstaticmethod
    • 3.3 @abstractproperty
  • 4. 注册虚拟子类
  • 5. 检查抽象方法
  • 6. 实际应用示例
  • 7. 注意事项
  • 8. 内置抽象基类

abc模块是Python标准库中提供抽象基类(Abstract Base Class)支持的模块,全称为"Abstract Base Classes"。它允许开发者定义抽象基类,这些类不能被实例化,主要用于作为其他类的基类来定义接口规范。

1. 为什么需要抽象基类 #

抽象基类的主要用途:

  • 定义接口规范,强制子类实现特定方法
  • 提供一种机制来检测对象是否遵循特定协议
  • 在大型项目中建立清晰的类层次结构和接口约定

2. 基本用法 #

2.1 创建抽象基类 #

本例演示如何使用abc模块定义一个抽象基类Animal。抽象基类用于规定接口规范,不能被实例化。通过@abstractmethod装饰器声明抽象方法,要求所有子类必须实现这些方法。

# 导入abc模块中的ABC和abstractmethod
from abc import ABC, abstractmethod

# 定义一个抽象基类Animal,继承自ABC
class Animal(ABC):
    # 定义抽象方法make_sound,子类必须实现
    @abstractmethod
    def make_sound(self):
        pass

    # 定义抽象方法move,子类必须实现
    @abstractmethod
    def move(self):
        pass

# 下面这行代码会报错,因为抽象类不能被实例化
# animal = Animal()  # TypeError: Can't instantiate abstract class Animal with abstract methods make_sound, move

2.2 实现抽象基类 #

本例演示如何继承抽象基类Animal并实现所有抽象方法。只有实现了所有抽象方法的子类才能被实例化。

# 导入abc模块中的ABC和abstractmethod
from abc import ABC, abstractmethod

# 定义抽象基类Animal
class Animal(ABC):
    @abstractmethod
    def make_sound(self):
        pass
    @abstractmethod
    def move(self):
        pass

# 定义Dog类,继承自Animal,实现所有抽象方法
class Dog(Animal):
    # 实现make_sound方法
    def make_sound(self):
        return "Woof!"
    # 实现move方法
    def move(self):
        return "Running on four legs"

# 定义Bird类,继承自Animal,实现所有抽象方法
class Bird(Animal):
    # 实现make_sound方法
    def make_sound(self):
        return "Chirp!"
    # 实现move方法
    def move(self):
        return "Flying"

# 测试代码
if __name__ == "__main__":
    dog = Dog()
    print(dog.make_sound())  # 输出: Woof!
    print(dog.move())        # 输出: Running on four legs
    bird = Bird()
    print(bird.make_sound()) # 输出: Chirp!
    print(bird.move())       # 输出: Flying

如果子类没有实现所有抽象方法,尝试实例化时会报错。

# 导入abc模块中的ABC和abstractmethod
from abc import ABC, abstractmethod

# 定义抽象基类Animal
class Animal(ABC):
    @abstractmethod
    def make_sound(self):
        pass
    @abstractmethod
    def move(self):
        pass

# 定义一个未实现抽象方法的子类
class IncompleteAnimal(Animal):
    pass

# 尝试实例化会引发 TypeError
if __name__ == "__main__":
    try:
        animal = IncompleteAnimal()
    except TypeError as e:
        print(e)  # 输出: Can't instantiate abstract class IncompleteAnimal with abstract methods make_sound, move

3. 其他装饰器 #

除了@abstractmethod,abc模块还提供了其他有用的装饰器:

3.1 @abstractclassmethod #

@abstractclassmethod用于声明抽象类方法,要求子类必须实现该类方法。

# 导入ABC和abstractclassmethod
from abc import ABC, abstractclassmethod

# 定义抽象基类Database
class Database(ABC):
    # 定义抽象类方法connect
    @abstractclassmethod
    def connect(cls, connection_string):
        pass

# 定义子类MySQLDatabase,实现抽象类方法
class MySQLDatabase(Database):
    @classmethod
    def connect(cls, connection_string):
        print(f"连接到MySQL数据库: {connection_string}")

# 测试代码
if __name__ == "__main__":
    MySQLDatabase.connect("mysql://localhost:3306/test")

3.2 @abstractstaticmethod #

@abstractstaticmethod用于声明抽象静态方法,要求子类必须实现该静态方法。

# 导入ABC和abstractstaticmethod
from abc import ABC, abstractstaticmethod

# 定义抽象基类MathOperations
class MathOperations(ABC):
    # 定义抽象静态方法add
    @abstractstaticmethod
    def add(a, b):
        pass

# 定义子类SimpleMath,实现抽象静态方法
class SimpleMath(MathOperations):
    @staticmethod
    def add(a, b):
        return a + b

# 测试代码
if __name__ == "__main__":
    print(SimpleMath.add(3, 5))  # 输出: 8

3.3 @abstractproperty #

在Python 3.3+中,推荐使用property与abstractmethod结合声明抽象属性,要求子类必须实现该属性。

# 导入ABC和abstractmethod
from abc import ABC, abstractmethod

# 定义抽象基类Shape
class Shape(ABC):
    # 定义抽象属性area
    @property
    @abstractmethod
    def area(self):
        pass

# 定义子类Circle,实现抽象属性area
class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    @property
    def area(self):
        return 3.14159 * self.radius ** 2

# 测试代码
if __name__ == "__main__":
    c = Circle(2)
    print(c.area)  # 输出: 12.56636

4. 注册虚拟子类 #

抽象基类允许注册"虚拟子类",这些类不需要直接继承自抽象基类,但会被视为其子类。

# 导入ABC
from abc import ABC

# 定义抽象基类Animal
class Animal(ABC):
    def make_sound(self):
        pass
    def move(self):
        pass

# 定义普通类WildDog
class WildDog:
    def make_sound(self):
        return "Wild Woof!"
    def move(self):
        return "Running wildly"

# 注册WildDog为Animal的虚拟子类
Animal.register(WildDog)

# 测试issubclass和isinstance
if __name__ == "__main__":
    print(issubclass(WildDog, Animal))  # 输出: True
    print(isinstance(WildDog(), Animal))  # 输出: True

5. 检查抽象方法 #

可以使用__abstractmethods__属性查看一个类的抽象方法集合。

# 导入ABC和abstractmethod
from abc import ABC, abstractmethod

# 定义抽象基类Animal
class Animal(ABC):
    @abstractmethod
    def make_sound(self):
        pass
    @abstractmethod
    def move(self):
        pass

# 查看Animal的抽象方法集合
if __name__ == "__main__":
    print(Animal.__abstractmethods__)  # 输出: frozenset({'make_sound', 'move'})

6. 实际应用示例 #

本例演示如何用抽象基类Shape定义图形的面积和周长接口,并实现Circle和Rectangle两个具体子类。

# 导入ABC和abstractmethod
from abc import ABC, abstractmethod
# 导入math模块
import math

# 定义抽象基类Shape
class Shape(ABC):
    # 定义抽象属性area
    @property
    @abstractmethod
    def area(self):
        pass
    # 定义抽象属性perimeter
    @property
    @abstractmethod
    def perimeter(self):
        pass

# 定义圆形类Circle,实现Shape接口
class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    @property
    def area(self):
        return math.pi * self.radius ** 2
    @property
    def perimeter(self):
        return 2 * math.pi * self.radius

# 定义矩形类Rectangle,实现Shape接口
class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    @property
    def area(self):
        return self.width * self.height
    @property
    def perimeter(self):
        return 2 * (self.width + self.height)

# 测试代码
if __name__ == "__main__":
    c = Circle(3)
    r = Rectangle(4, 5)
    print(f"圆面积: {c.area:.2f}, 圆周长: {c.perimeter:.2f}")
    print(f"矩形面积: {r.area}, 矩形周长: {r.perimeter}")

7. 注意事项 #

  1. 抽象基类本身不能被实例化
  2. 子类必须实现所有抽象方法才能被实例化
  3. 抽象方法可以有实现,但通常不推荐这样做
  4. Python中的抽象基类更多是一种约定,不像Java等语言有严格的接口检查

8. 内置抽象基类 #

Python的collections.abc模块定义了许多有用的抽象基类,如:

  • Container
  • Iterable
  • Sequence
  • Mapping
  • 等等

这些抽象基类可以用于检查对象是否支持特定协议,比如判断一个对象是否为序列类型。

# 导入Sequence抽象基类
from collections.abc import Sequence

# 定义一个处理序列的函数
def process_sequence(seq):
    # 判断seq是否为Sequence类型
    if not isinstance(seq, Sequence):
        raise TypeError("Expected a sequence")
    # 处理序列,这里简单打印
    print("序列长度:", len(seq))

# 测试代码
if __name__ == "__main__":
    process_sequence([1, 2, 3])  # 正常
    try:
        process_sequence(123)    # 抛出TypeError
    except TypeError as e:
        print(e)

abc模块为Python提供了一种强大的方式来定义接口规范和建立清晰的类层次结构,是设计大型Python项目时的重要工具。

访问验证

请输入访问令牌

Token不正确,请重新输入