0

0

Python 组合优于继承的落地实践

冷炫風刃

冷炫風刃

发布时间:2026-02-15 13:09:12

|

548人浏览过

|

来源于php中文网

原创

该用 composition 而非 inheritance 当子类仅需复用部分逻辑却被迫继承无关行为时;优先用于功能可拆解、组合多变、“拥有”而非“是”的场景,而 inheritance 适用于明确 is-a 关系、框架强制或多态稳定需求。

python 组合优于继承的落地实践

什么时候该用 composition 而不是 inheritance

当你发现子类只为了复用某块逻辑,却被迫继承一整套无关的属性、方法或生命周期行为时,composition 就该上场了。比如写一个 FileProcessor 类,它需要“能重试”“能记录日志”“能校验格式”,但这些能力各自独立、可插拔——硬套继承链(RetryableFileProcessorLoggableRetryableFileProcessor)只会让类爆炸。

常见错误现象:isinstance(obj, BaseClass) 返回 True,但你根本不需要它的类型语义,只是想调用其中两个方法;或者修改父类一个私有方法,下游十几个子类突然行为异常。

  • 优先选 composition 的场景:功能可拆解、组合方式多变(如策略切换)、依赖关系松散(比如“拥有一个”而不是“是一种”)
  • 仍适合 inheritance 的场景:明确的 is-a 关系(DogAnimal)、框架强制要求(如 Django 的 View 子类)、需多态分发且接口稳定
  • inheritance 会隐式传递 __init____dict__MRO 链,而 composition 的初始化和属性访问完全由你控制,更易测、更易 debug

__getattr____getattribute__ 哪个更适合代理委托

想让容器类透明暴露被组合对象的方法?别急着重写一堆 def method(self, *a, **kw): return self._wrapped.method(*a, **kw) —— 用 __getattr__ 更轻量、更安全。

为什么不用 __getattribute__:它拦截所有属性访问(包括 self.__dict__),一不小心就递归崩溃;而 __getattr__ 只在常规查找失败后触发,天然适配“找不到才委托”的语义。

立即学习Python免费学习笔记(深入)”;

上班人导航
上班人导航

上班人必备的职场办公导航网站

下载
  • 典型误用:__getattribute__ 里直接访问 self._wrapped,导致无限递归(因为访问 self._wrapped 又触发 __getattribute__
  • 正确姿势:在 __getattr__ 中显式检查 hasattr(self._wrapped, name),再返回 getattr(self._wrapped, name),避免把私有属性(如 _cache)也透传出去
  • 性能影响:每次未命中的属性访问都会走一次 __getattr__,高频调用的属性(如循环里的 item.id)建议提前绑定到实例上,或改用显式方法封装

typing.Protocol 替代抽象基类做组合契约

组合对象之间需要约定“你能做什么”,但又不想绑死继承关系?typing.Protocolabc.ABC 更贴合组合场景——它只关心结构,不关心类型来源。

比如定义一个 Storable 协议,只要对象有 save()load() 方法就能被 BackupService 接受,不管它是从 DatabaseFileSystem 还是 mock 出来的。

  • 兼容性注意:Protocol 在运行时不检查(仅静态类型检查器如 mypy 生效),若需运行时断言,得加 isinstance(obj, Storable) + 手动 hasattr 判断
  • 参数差异:Protocol 不支持 @abstractmethod 的运行时强制,也不参与 MRO,所以不会干扰组合对象自身的继承体系
  • 容易踩的坑:协议里写了 def close(self) -> None:,但实际对象用的是 def shutdown(self) -> None: —— 名字不一致就失效,协议不是模糊匹配

嵌套组合时如何避免 self._inner._inner._inner 链式调用

三层以上组合(A 包 B,B 包 C)会让调用变得丑陋又脆弱:a.b.c.do_something() 一旦中间环节变更,所有调用点都得改。这时候得靠“扁平化委托”或“上下文感知”来收口。

核心思路:容器类不该暴露内部层级,而是把最终能力封装成自己的方法,哪怕只是转发。

  • 推荐做法:在顶层类中定义 def do_something(self): return self._b.do_something(),即使 _b 再包 _c,这个方法内部可以自己处理跳转,外部无感
  • 反模式:property 直接返回 self._b._c,等于把内部结构白送出去,下次重构必崩
  • 调试提示:打印 obj.__class__.__mro__ 看继承链没用,组合对象的调用栈是纯函数调用链,出错时堆栈里不会出现“组合路径”,得靠日志打点或 breakpoint() 逐层进

组合真正的复杂点不在写法,而在边界划分——哪个类该负责重试,哪个该管超时,哪个只做数据转换。这些决策一旦模糊,再多的委托技巧也救不了混乱的职责分配。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python Web 框架 Django 深度开发
Python Web 框架 Django 深度开发

本专题系统讲解 Python Django 框架的核心功能与进阶开发技巧,包括 Django 项目结构、数据库模型与迁移、视图与模板渲染、表单与认证管理、RESTful API 开发、Django 中间件与缓存优化、部署与性能调优。通过实战案例,帮助学习者掌握 使用 Django 快速构建功能全面的 Web 应用与全栈开发能力。

60

2026.02.04

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

22

2025.11.27

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

22

2025.11.27

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

22

2025.11.27

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

22

2025.11.27

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1462

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

382

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2222

2025.12.29

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

145

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 4.3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号