为何已在子类实现抽象类属性,中间类仍需定义该属性?
问题解答
核心原因:Python抽象类的检查时机
Python的abc模块有个关键规则:当你定义一个继承抽象类的子类时,如果这个子类不是抽象类,就必须立刻实现父类所有的抽象成员——这个检查在类定义完成时就会执行,不是等到实例化最终子类的时候。
你定义的InterClass继承了AbcClass,但没实现MAP,也没把自己标记为抽象类,那Python就会认为InterClass是一个“不完整”的非抽象类,违反了抽象类的契约。哪怕你在ConcreteClass里补了MAP,但InterClass本身的抽象状态已经有问题了,所以实例化时还是会报错。
为什么要这么设计?
抽象类的核心作用就是给子类定规矩:所有继承它的非抽象子类,必须实现约定好的抽象成员。如果允许中间类跳过去实现,那这个中间类本身就成了一个“不合格”的子类——它既不是抽象类(不能用来约束子类),又没遵守父类的规矩,这就违背了抽象类的设计初衷。
解决办法
有两种简单的处理方式:
- 让InterClass保持抽象类状态:不需要在
InterClass里定义MAP,只要它继承了抽象类但没实现所有抽象成员,Python会自动把它当成抽象类,把实现MAP的责任交给它的子类。修改后的InterClass就是你注释掉MAP = None的样子,直接用就行:
class InterClass(AbcClass): @property def text(self) -> str: return "text"
此时InterClass是抽象类,Python不会要求它实现MAP,只会检查最终的ConcreteClass是否完成了所有抽象成员的实现。
- 在InterClass里重新声明抽象MAP:如果你想更清晰地传递抽象契约,可以在
InterClass里重新定义MAP为抽象属性,明确告诉子类必须实现它:
class InterClass(AbcClass): @classmethod @property @abstractmethod def MAP(cls) -> Dict[str, str]: raise NotImplementedError @property def text(self) -> str: return "text"
这样InterClass依然是抽象类,直到ConcreteClass实现MAP后才能被实例化。
验证修改后的代码
用第一种方案的完整代码示例:
from abc import ABC, abstractmethod from typing import Dict class AbcClass(ABC): @classmethod @property @abstractmethod def MAP(cls) -> Dict[str, str]: raise NotImplementedError @property def map(self) -> Dict[str, str]: return self.MAP class InterClass(AbcClass): @property def text(self) -> str: return "text" class ConcreteClass(InterClass): MAP = { "a": "b" } c = ConcreteClass() print(c.map) # 输出: {'a': 'b'}
运行这段代码就不会再触发NotImplementedError了。
内容的提问来源于stack exchange,提问作者GuillaumeA
相关产品推荐
相关产品推荐

