python 抽象类的使用详解
前言抽象类abstract class要解决的问题很具体我想定义一个概念上的基类它规定了子类必须实现哪些方法自己却不提供完整实现也不应该被直接实例化。Python 里靠自己写一个方法体里raise NotImplementedError也能模拟出效果但那只是软约束——类照样能被实例化只有真正调用到那个方法时才会报错。要得到没实现完就不许实例化这种硬约束得用标准库abc模块里的抽象基类Abstract Base ClassABC。围绕抽象类有两个常见误解需要先澄清第一以为 ABC 的主要用途是跑起来时做类型检查。其实 ABC 最大的价值在接口约定——它在类被实例化的那一刻就拦住实现不全的子类把错误从运行时推迟到更早、更容易定位的位置。第二以为用了register()注册的类就跟继承一样了。实际上虚拟子类只是通过issubclass()/isinstance()检查它不出现在 MRO 里ABC 定义的方法也不会被它继承到。本文讲abc.ABC、abstractmethod的用法与边界并给出可直接运行的示例。一、abc.ABC 与 abstractmethodabc模块提供辅助类ABC它本身的元类metaclass是ABCMeta。从ABC派生就能以最普通的继承写法创建抽象基类而不必手动折腾metaclass。abstractmethod是声明抽象方法的装饰器。文档说明使用它要求所在类的元类是ABCMeta或它的子类而带有ABCMeta派生元类的类只要还有未覆盖的抽象方法或抽象属性就不能被实例化。# 适用于 Python 3.8from abc import ABC, abstractmethodclass Storage(ABC):abstractmethoddef save(self, key, value):...abstractmethoddef load(self, key):...class MemoryStorage(Storage):def __init__(self):self._data {}def save(self, key, value):self._data[key] valuedef load(self, key):return self._data.get(key)s MemoryStorage()s.save(a, 1)print(s.load(a)) # 1如果此时直接写Storage()会立刻抛TypeError: Cant instantiate abstract class Storage with abstract methods load, save。如果子类只实现了save没有实现load那么MemoryStorage()同样会抛TypeError错误信息里会点名还没实现的方法。注意上面save/load的方法体是...省略号。抽象方法可以带实现子类可以用super()调到它——文档明确说抽象方法可以通过任何常规的 super 调用机制被调用。所以下面这种写法是成立的# 适用于 Python 3.8from abc import ABC, abstractmethodclass Renderer(ABC):abstractmethoddef render(self, text):return text.strip() # 提供一份默认实现class HtmlRenderer(Renderer):def render(self, text):return p super().render(text) /p二、抽象属性与装饰器顺序抽象方法也能和property、classmethod、staticmethod组合。文档给出一条硬规则abstractmethod要放在最内层也就是紧贴def的那一行。# 适用于 Python 3.8from abc import ABC, abstractmethodclass Config(ABC):propertyabstractmethoddef path(self):...classmethodabstractmethoddef from_env(cls):...class FileConfig(Config):def __init__(self, path):self._path pathpropertydef path(self):return self._pathclassmethoddef from_env(cls):return cls(default.conf)顺序写反abstractmethod在最外层不会达到预期效果因为外层的装饰器会先把它包装掉。另外早期常用的abc.abstractproperty从 Python 3.3 起就已弃用property与abstractmethod组合已经能正确表达抽象属性那个装饰器是多余的。新代码不要再用。三、虚拟子类与 __subclasshook__有些类已经存在甚至是内置类没法改它的继承关系但又希望isinstance认它。这时用register()ABC 的元类提供register(subclass)把参数注册成虚拟子类。# 适用于 Python 3.8from abc import ABCclass Sized(ABC):passSized.register(tuple)print(issubclass(tuple, Sized)) # Trueprint(isinstance((), Sized)) # True有个重要限制虚拟子类不会出现在 MRO 里ABC 定义的方法也不能被它通过super()调到。所以register()只影响类型检查结果不带来任何实现复用。__subclasshook__则更进一步它是一个必须在 ABC 里定义成classmethod的钩子让issubclass()的判定可以自定义从而不必给每个类都手动register()。它应返回True、False或NotImplemented返回NotImplemented时检查会回落到常规机制。标准库collections.abc.Iterable就是这么判定有没有__iter__的。下表梳理abc模块的几个常用入口名称类型作用ABC辅助基类元类为ABCMeta直接继承即可定义 ABCABCMeta元类需要自定义元类时使用abstractmethod装饰器声明抽象方法须放在装饰器最内层register(subclass)方法注册虚拟子类不影响 MRO__subclasshook__类方法自定义issubclass()判定update_abstractmethods(cls)函数3.10重算抽象状态通常用于类装饰器四、标准库里现成的 ABC不是所有场景都要自己定义 ABC。标准库已经准备了一批常用接口放在collections.abcIterable、Sequence、MutableSequence、Mapping等、numbers、io和importlib.abc里。# 适用于 Python 3.8from collections.abc import Sequenceclass MyList:def __init__(self, data):self._data list(data)def __getitem__(self, index):return self._data[index]def __len__(self):return len(self._data)Sequence.register(MyList)print(isinstance(MyList([1, 2]), Sequence)) # True需要判断能不能迭代时文档提醒过isinstance(obj, Iterable)能识别注册过的类和带__iter__的类但识别不了仅用__getitem__迭代的旧式类。常见坑点1. 以为raise NotImplementedError就等于抽象方法❌# 适用于 Python 3.8class Base:def run(self):raise NotImplementedErrorBase()能正常创建错误要等到调用run()才暴露。✅# 适用于 Python 3.8from abc import ABC, abstractmethodclass Base(ABC):abstractmethoddef run(self):...Base()当场就抛TypeError。2. 子类只实现了部分抽象方法就实例化❌ 以为实现了主要的那个方法就行结果一实例化就TypeError报错还点名漏了哪个方法。✅ 要么把全部抽象方法补上要么给子类也加上abstractmethod让它继续当抽象类。3. 装饰器顺序写反❌# 适用于 Python 3.8class C(ABC):abstractmethodpropertydef x(self):...✅# 适用于 Python 3.8class C(ABC):propertyabstractmethoddef x(self):...4. 还在用abstractproperty/abstractclassmethod❌ 从abc导入abstractproperty当新代码用它们是历史遗留从 3.3 起已弃用。✅ 用propertyabstractmethod组合或classmethodabstractmethod。5. 以为register()注册的类能继承 ABC 的方法❌Sized.register(tuple)之后以为tuple会多出 ABC 里定义的size()方法。✅ 虚拟子类只影响isinstance/issubclass不进 MRO也拿不到方法实现。6. 想动态改抽象状态却直接改类属性❌ 创建类之后再往__abstractmethods__上乱动手脚。✅ 用abc.update_abstractmethods(cls)需要 Python 3.10 及以上该函数假定父类已经更新完且不会自动更新子类。7. 用ABCMeta手动配元类却和已有元类冲突❌ 一个类既想用ABCMeta又想用别的元类直接写两个metaclass。✅ 优先继承abc.ABC确实需要组合元类时得自己写一个派生自各方的元类。8. 把 ABC 当性能敏感处的类型检查手段❌ 在热点循环里对虚拟子类频繁isinstance检查。✅ ABC 的虚拟子类判定要走额外逻辑开销高于对普通类做isinstance热点路径上优先用鸭子类型或hasattr。总结目标做法定义接口、禁止不完整实例化继承abc.ABC方法加abstractmethod抽象属性property在外、abstractmethod在内复用父类默认实现抽象方法写方法体子类用super()调用让已有类通过类型检查ABC.register(类)3.3 返回被注册的类自动判定结构重写__subclasshook__类方法用现成接口collections.abc、numbers、io里的 ABC抽象基类的核心价值是把接口契约提前到实例化那一刻强制检查让缺失实现这类错误尽早暴露。同时要记住它的边界虚拟子类只改变类型判定不带来实现复用抽象方法可以有实现但装饰器顺序必须对。把这两点拿捏准abc用起来就没什么意外。

相关新闻

python 爬虫如何正确的使用cookie

python 爬虫如何正确的使用cookie

前言 先把最要紧的一句放在开头:Cookie 等同于你的登录凭据。它不是一个普通的请求参数,而是服务端下发给你、用来在后续请求里认出「你还是刚才那个人」的凭据。理解这一点之后,下面的两条铁律就顺理成章了:绝不能把自己的 Cooki…

2026/11/6 5:41:05 阅读更多 →
C++23工程实践指南:expected、mdspan与print等实用特性详解

C++23工程实践指南:expected、mdspan与print等实用特性详解

C23的正式标准在2023年末冻结,不像C20那样一口气端出协程、模块、概念、ranges四座大山,但它对工程项目的实际影响,在我看来比C20更直接。C23没去折腾新的语法大概念,而是把错误处理、多维数组、格式化输出、调用栈诊断这些日常开…

2026/11/11 12:42:47 阅读更多 →
python 特殊属性及方法详细解析

python 特殊属性及方法详细解析

前言 「特殊属性」和「特殊方法」这两个词经常被混着用,其实它们在语言参考里是两套不同的东西。特殊方法(也叫魔术方法)是那些会被语法隐式调用的、可调用的下划线方法,比如 __init__、__len__;特殊属性是那些由解释器…

2026/11/6 6:04:47 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/10 23:32:01 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/10 23:32:03 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/11 2:31:33 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/10 16:14:15 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/10 12:51:50 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/10 23:32:10 阅读更多 →

日新闻

周新闻

月新闻