抽象基类必须显式继承abc才能生效,仅用@abstractmethod装饰器无效;继承后未实现抽象方法时实例化会抛typeerror;@abstractmethod不支持静态方法和变量,子类必须完整重写抽象property或类方法。

抽象基类必须继承 ABC,不能只靠 @abstractmethod
很多人写完 @abstractmethod 就以为定义好了抽象类,结果实例化不报错——这是因为没让类真正成为抽象基类。Python 要求:必须显式继承 ABC(或其子类),否则 @abstractmethod 仅是装饰器,不起强制约束作用。
-
ABC来自from abc import ABC, abstractmethod,不是内置类,也不能用class MyABC(metaclass=ABCMeta)手动指定元类(除非有特殊需求) - 继承
ABC后,只要含未实现的@abstractmethod,直接MyABC()就会抛TypeError: Can't instantiate abstract class ... with abstract method ... - 如果类只是“逻辑上抽象”,但允许实例化(比如带默认实现的模板类),那就别继承
ABC,也别加@abstractmethod
@abstractmethod 只能修饰方法、属性、property 和类方法
它不能用在静态方法(@staticmethod)上——Python 会静默忽略,不报错也不生效;也不能修饰普通变量或注释。常见误用是想让某个配置字段“必须由子类提供”,结果写成:
@abstractmethod CONFIG_PATH = "/default"
这不会起作用。正确做法是:把它转为 property 或方法:
@property
@abstractmethod
def CONFIG_PATH(self):
...
- 支持修饰
def method(self):(实例方法)、@classmethod、@property,但不支持@staticmethod - 抽象 property 的子类必须重写同名 property(不能只重写 getter 或 setter,得整个重新定义)
- 抽象类方法的子类必须用
@classmethod实现,且签名需兼容(至少包含cls)
子类不实现抽象成员时,错误只在实例化时触发
Python 不在导入或定义子类时检查抽象方法是否被实现,而是在你第一次调用 SubClass() 时才校验。这意味着:
- 即使子类忘了实现某个
@abstractmethod,代码也能正常 import、甚至能调用它的其他已实现方法 - 测试时容易漏掉,建议在单元测试中对每个抽象基类的子类做一次实例化断言
- 如果子类只是中间层(本身也不该被实例化),那它也应该继承
ABC,否则无法阻止下游误实例化
用 isinstance 和 issubclass 判断抽象类关系要小心注册
默认情况下,只有显式继承才能被 isinstance(obj, MyABC) 或 issubclass(Sub, MyABC) 识别。但你可以用 MyABC.register(ConcreteClass) 手动注册“鸭子类型”类——这时 isinstance 会返回 True,但 ConcreteClass 依然不会受抽象方法约束(不强制实现,也不参与 MRO 查找)。
- 注册后,
issubclass(ConcreteClass, MyABC)返回True,但ConcreteClass仍可被实例化,哪怕它没实现任何抽象方法 - 注册纯属运行时类型提示,不影响语法或逻辑校验,慎用于需要强契约的场景
- 真正需要多态+强制实现,就别注册,老实用继承
ABC 这一步,而它的检查时机又非常晚——这两个点最容易被忽略,一漏就是线上运行时报错。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











