Python3中允许子类自定义属性的抽象基类的规范写法是怎样的?
关于抽象基类初始化写法的说明
现有写法的合规性分析
你当前的写法可以正常运行,也满足强制子类实现指定方法的功能需求,但不符合Python常规编码规范,存在可优化空间:
- 存在重复代码:两个公共属性
_common_1、_common_2的初始化逻辑在每个子类都重复实现,后续如果需要调整公共属性的默认值、新增公共属性,需要修改所有子类,维护成本高 - 无意义的抽象方法标记:
__init__不需要被标记为抽象方法,公共属性的初始化逻辑完全可以在基层统一实现,不需要强制每个子类重写 - 缺少前置校验:如果某个子类漏写了公共属性的初始化,只有在运行到调用该属性的逻辑时才会报错,无法在实例化阶段就暴露问题
更推荐的实现方式
你在教程中看到的「基类实现__init__,子类通过super().__init__()调用」的方式更符合Python编码规范,专业度更高,优势如下:
- 公共逻辑收敛:所有公共属性的初始化逻辑统一收在抽象基类中,后续修改只需要调整基类代码,不需要修改子类
- 减少出错概率:只要子类调用了基类的初始化方法,就必然存在约定的公共属性,不会出现漏写的问题
- 代码更简洁:子类不需要重复写公共属性的初始化代码,只需要实现自身特有的属性逻辑即可
优化后的代码示例
from abc import ABC, abstractmethod from typing import Dict, List class CaseBase(ABC): # __init__不需要标记为抽象方法,基类直接实现公共属性初始化 def __init__(self): self._common_1: Dict[str, float] = {} self._common_2: List[float] = [] @abstractmethod def get_input(self, input_data: dict): ... @abstractmethod def run(self): ... class CaseA(CaseBase): def __init__(self): # 先调用基类初始化,拿到公共属性 super().__init__() # 仅实现子类特有的属性 self._a1: int = 0 self._a2: str = '' def get_input(self, input_data: dict): self._common_1 = input_data['common_1'] self._common_2 = input_data['common_2'] self._a1 = input_data['a1'] self._a2 = input_data['a2'] def run(self): print(self._common_1) print(self._common_2) print(self._a1) print(self._a2)
如果你的业务场景确实存在特殊情况,子类不能调用基类的__init__方法,必须完全重写初始化逻辑,那你把基类的__init__标记为抽象方法的写法也是可以接受的,属于特殊场景下的合理实现。
内容的提问来源于stack exchange,提问作者aura
相关产品推荐
相关产品推荐

