当前位置: 首页 > news >正文

[Python 基础课程]抽象类

在 Python 中,抽象类(Abstract Class) 是一种特殊的类,它不能被直接实例化(也就是你不能直接创建它的对象),它的主要目的是作为其他类的基类(父类),来定义一组必须由子类实现的方法

你可以把抽象类想象成一份“合同”或者“行为规范”。它规定了所有继承它的子类必须具备哪些功能(抽象方法),但它自己并不知道这些功能具体该如何实现。具体的实现细节,则留给子类去完成。

为什么需要抽象类

考虑这样一个场景:你正在开发一个图形绘制程序,里面有各种各样的图形:圆形、矩形、三角形等。它们都有一些共同的行为,比如计算面积和计算周长。

如果直接这样写:

# class Circle:
#     def calculate_area(): ...
#     def calculate_perimeter(): ...# class Rectangle:
#     def calculate_area(): ...
#     def calculate_perimeter(): ...# class Triangle:
#     def calculate_area(): ...
#     def calculate_perimeter(): ...

这看起来没问题,但如果你在代码中写了一个处理通用图形的函数:

# def print_shape_info(shape):
#     # 如果 shape 没有 calculate_area 方法,这里就会报错!
#     print(f"面积: {shape.calculate_area()}")
#     print(f"周长: {shape.calculate_perimeter()}")

你如何确保所有传入 print_shape_info 函数的 shape 对象都一定calculate_area()calculate_perimeter() 这两个方法呢?在没有抽象类的情况下,这只能依靠程序员的约定和自律。一旦有哪个新图形类忘记实现这些方法,就会在运行时出错。

抽象类的作用就是:

  • 定义统一接口: 强制子类实现某些特定的方法,确保所有派生类都符合预期的行为规范。
  • 提供基础骨架: 可以在抽象类中实现一些通用方法,供子类共享,避免代码重复。
  • 防止不完整实例化: 阻止创建没有实现所有必要功能的父类对象。

定义抽象类

Python 通过内置的 abc 模块(Abstract Base Classes)来支持抽象类。

核心要素:

  • ABC:抽象基类模块中的一个类,你的抽象类需要继承它。
  • @abstractmethod 一个装饰器,用于标记抽象类中的方法,表示这些方法必须由子类实现。
from abc import ABC, abstractmethodclass AbstractClassName(ABC): # 你的抽象类需要继承 ABC@abstractmethoddef abstract_method_one(self, param):"""这是一个抽象方法,子类必须实现它。它只有声明,没有具体的实现。"""pass # 或者 raise NotImplementedError("子类必须实现此方法")@abstractmethoddef abstract_method_two(self):"""另一个抽象方法。"""passdef concrete_method(self):"""这是一个具体方法,抽象类可以有自己的实现。子类可以选择重写或直接继承。"""print("这是一个具体方法,可以在抽象类中实现。")

我们来用抽象类解决前面提到的图形绘制问题:

from abc import ABC, abstractmethod# 定义一个抽象基类 Shape
class Shape(ABC):@abstractmethoddef calculate_area(self):"""计算图形的面积"""pass@abstractmethoddef calculate_perimeter(self):"""计算图形的周长"""passdef get_description(self):"""这是一个具体方法,子类可以直接继承"""return "这是一个通用图形。"# 实现具体的圆形类
class Circle(Shape):def __init__(self, radius):self.radius = radiusdef calculate_area(self):return 3.14159 * self.radius * self.radiusdef calculate_perimeter(self):return 2 * 3.14159 * self.radius# 实现具体的矩形类
class Rectangle(Shape):def __init__(self, length, width):self.length = lengthself.width = widthdef calculate_area(self):return self.length * self.widthdef calculate_perimeter(self):return 2 * (self.length + self.width)# 尝试创建一个没有实现所有抽象方法的类会报错
# class IncompleteShape(Shape):
#     def calculate_area(self):
#         return 0 # 只实现了一个# --- 演示与测试 ---# 无法直接实例化抽象类
# my_abstract_shape = Shape() # 这行会抛出 TypeErrorcircle = Circle(5)
rectangle = Rectangle(4, 6)print(f"圆形描述: {circle.get_description()}")
print(f"圆形面积: {circle.calculate_area()}")
print(f"圆形周长: {circle.calculate_perimeter()}")print("-" * 20)print(f"矩形描述: {rectangle.get_description()}")
print(f"矩形面积: {rectangle.calculate_area()}")
print(f"矩形周长: {rectangle.calculate_perimeter()}")print("-" * 20)# 前面提到的通用函数现在可以安全使用了
def print_shape_info(shape: Shape): # 可以用类型提示增强可读性print(f"--- {type(shape).__name__} 信息 ---")print(f"描述: {shape.get_description()}")print(f"面积: {shape.calculate_area()}")print(f"周长: {shape.calculate_perimeter()}")print("-" * 20)print_shape_info(circle)
print_shape_info(rectangle)# 如果你尝试创建 IncompleteShape 的实例,会报错:
# incomplete = IncompleteShape() # TypeError: Can't instantiate abstract class IncompleteShape with abstract method calculate_perimeter

代码解释:

  1. class Shape(ABC):Shape 类继承自 ABC,表明它是一个抽象基类。
  2. @abstractmethod:装饰器 calculate_areacalculate_perimeter 方法,强制任何继承 Shape 的子类都必须实现这两个方法。
  3. CircleRectangle 类都继承了 Shape,并且强制性地实现了 calculate_areacalculate_perimeter
  4. get_description() 是一个具体方法,它在抽象类中提供了实现,子类可以直接继承使用,也可以根据需要重写。
  5. 当你尝试创建 Shape() 的实例时,Python 会抛出 TypeError,因为它是抽象类,不能直接实例化。
  6. 当你尝试创建 IncompleteShape() 的实例时,即使它继承了 Shape,但由于没有实现所有抽象方法,也会抛出 TypeError

抽象类和接口的关联

在 Java 或 C# 等语言中,有明确的 interface 关键字来定义接口。Python 没有这个关键字,但抽象类在很多情况下可以被看作是 Python 实现“接口”的一种方式

  • 抽象类作为接口: 当一个抽象类中所有的方法都是抽象方法(即没有具体实现)时,它就非常类似于其他语言中的接口。它只定义了一套行为规范
  • 抽象类与具体方法: 抽象类还可以包含具体的(已实现)方法,这是与纯接口的不同之处。这允许你在接口中定义一些通用的功能,供所有子类共享
http://www.dtcms.com/a/334386.html

相关文章:

  • 强化学习入门教程(附学习文档)
  • (第十七期)HTML图像标签详解:从入门到精通
  • 创新词汇表设计:UniVoc - 中英文混合处理的新方案
  • 安卓11 12系统修改定制化_____列举与安卓 9、10 系统在定制化方面的差异与权限不同
  • 数学建模Topsis法笔记
  • 非功能性需求设计:可解释性、鲁棒性、隐私合规
  • 【数据结构初阶】--排序(五):计数排序,排序算法复杂度对比和稳定性分析
  • 启发式合并 + 莫队 恋恋的心跳大冒险
  • 汽车大灯ABD算法介绍
  • 【算法】——力扣hot100常用算法技巧
  • leetcode_ 739 每日温度
  • 分享一个大数据的源码实现 基于Hadoop的二手车市场数据分析与可视化 基于Spark的懂车帝二手车交易数据可视化分析系统
  • Windows MCP.Net:革命性的 .NET Windows 桌面自动化 MCP 服务器
  • 嵌入式硬件篇---电容电感
  • 【C++】动态内存管理
  • 嵌入式硬件篇---电平转换电路
  • Python-深度学习(一)
  • Flutter开发 网络请求
  • Obot MCP 网关:用于安全管理 MCP 服务器采用的开源平台
  • DINOv3 论文精读(逐段解析)
  • 一文速通Python并行计算:14 Python异步编程-协程的管理和调度
  • CPP运算符优先级
  • 2508C++,支持rdma通信的高性能rpc库
  • 软件SPI实现(3):SPI协议测试(使用W25Q64)
  • Jenkins常见问题及解决方法
  • 计算机存储器分类和层次结构详解
  • 027 动静态库 —— 静态库
  • Docker数据卷挂载和本地目录挂载
  • 八、SpringBoot项目热部署
  • Java服务自动停止原因及查找方法