Python中的接口、抽象基类和协议

Python中的接口、抽象基类和协议

接口与抽象基类

在面向对象的世界中,我们应该对接口编程,而不是实现。我们的代码应该依赖于对象能做什么(抽象),而不是对象具体是谁(具体实现)。

下面通过吃汉堡的例子来演示一下。

依赖具体实现

通过上面的例子可以看到,一旦要换不同具体实现的汉堡,就必须修改人类的代码。
面向接口编程实现依赖倒置

通过上面的代码可以看到,我们使用了abc写了一个抽象基类Burger,对于类Human的eat_lunch方法只是依赖了Burger,而不是依赖了具体某个诸如ChickenBurger的实现类。后续Human想要吃别的汉堡,我们一行代码都不需要改,只需要继承基类,然后实现具体的类就可以了,这就是依赖倒置!

而这种使用抽象基类实现依赖倒置的方式,是一种硬契约!
Python中的类型检查

请注意,在Python中的类型注解并不会强制检查,而只是一种静态检查,Python解释器不会去理会参数的类型注解。

可以看到,即使上面传入的不是显式继承汉堡基类的实例,也可以成功运行。因为类型注解只是静态检查。如果我们想要运行时检查,就得使用isinstance()显式检查。虚拟子类

但是这样做,其实也可以通过骚操作绕过去——虚拟子类

上面代码通过把饺子注册为汉堡的虚拟子类,代码可以跑通。
但是,从纯粹的面向对象理论来看,频繁使用普通类去进行isinstance()检查,确实在很大程度上违背了 Python 核心的“鸭子类型”(Duck Typing)设计哲学。在Python中其实并不怎么关注血统,更在意的其实是能力。

协议

在计算机世界里面,在不同语境下的协议具有不同的意思。比如我们最熟悉的HTTP这种网络协议指明了客户端可向服务器发送的命令,例如get,put,post。而Python中的对象协议则指明了为履行某个角色,对象必须实现哪些方法。协议相对于上面展示的面向接口编程,其实是更高层级的抽象,完美诠释了鸭子类型的设计哲学,只关注对象拥有什么能力,而不是去关注血统(父子类显式继承)。

一个展示Python协议神奇之处的例子:

如果不熟悉Python的读者一定会对代码的结果感到惊讶,明明MyIter和Iterable并没有任何显式继承的关系,但是isinstance(counter, Iterable)居然返回了Ture!这就是Python协议的强大之处,目标有__iter__(迭代)的能力,我就认为你是一个迭代器,无需任何显式继承。
上下文管理器协议(Context Manager Protocol)

Python 的协议(Protocol)打破了接口的最后一道枷锁——显式继承。它告诉我们,最高级的抽象不是去画一张完美无缺的物种分类图,而是去定义一套纯粹的行为契约。

通过上面的例子(ai写的)可以看出,两个上下文管理对象没有任何显式继承,但是却能被with这个上下文管理器。原因就在于DatabaseConnection和MagicalPortal都实现了上下文管理器的协议。
静态协议

Protocol(静态协议)是Python在3.8引入的,通过上面的关于协议的讲解,我们可以发现,协议的坏处就是没有类型提示,所以往往我们可能去调用一个对象不存在的方法,而我们很难在写代码的时候通过Mypy或者是IDE发现。 @runtime_checkable

在使用 typing.Protocol 时,我们获得了极佳的静态类型提示体验(IDE 提供智能补全,mypy 静态检查能通过)。但是,由于 Protocol 纯粹是为“静态检查”设计的,如果你尝试在代码运行阶段使用 isinstance() 去验证一个对象是否符合静态协议,Python 会直接拒绝执行并抛出异常!

为了解决这个问题,让协议既能享受静态类型检查的红利,又能像普通的类一样在运行时使用 isinstance() 进行鸭子类型判断,Python 的 typing 模块提供了 @runtime_checkable 装饰器。

它的底层原理,正是我们在上文提到的 __subclasshook__ 黑魔法。加上这个装饰器后,Python 会自动在底层拦截 isinstance() 调用,去动态检查对象是否拥有协议中定义的那些方法或属性。

使用协议实现依赖倒置

上面我们在讲接口和抽象基类的时候,通过一个汉堡的例子向读者展示怎样实现依赖倒置。这是通过定义抽象基类,让具体实现继承抽象基类Burger这个“硬契约”来实现的。而Python中的协议其实是更加深层次的抽象,我们无需显式继承,通过实现一套“软契约”来实现。如果说继承是强硬法律的话,协议则更像是一种君子协定。

通过上面的代码,我们可以看到,我们实现的这套“软契约”其实就是目标对象有没有eat这个方法,有我就认为你是汉堡。为什么说这是更加抽象的方式,因为我们在解耦了汉堡的具体实现与人类的耦合的同时,还无需去显式继承任何基类。显式继承 (ABC):不仅要求类具备某些方法,还强制要求类在“族谱”上属于某个基类(强耦合的 is-a 关系)。协议 (Protocol):完全不在乎对象是从哪里来的、继承自谁,只关心它能不能做这件事(can-do 关系)。实现类根本不需要知道协议的存在,也不需要导入协议所在的模块,这就实现了真正的业务逻辑与接口定义的彻底解耦。
协议黑魔法

现在回到我们开头那个迭代器协议的例子,Python是如何“偷偷”实现这个协议的

其实秘密就在于__subclasshook__这个魔法方法,

当我们调用 isinstance(obj, SomeABC) 时,Python 内部的逻辑流如下:显式继承,检查 obj 的类是否继承自 SomeABC。虚拟子类注册,检查 obj 的类是否通过 SomeABC.register() 注册过。关键点:调用 SomeABC.__subclasshook__(cls)。如果这个方法返回 True,那么即使前两条都不满足,isinstance 也会返回 True

所以Iterable协议就是通过定义__subclasshook__这个方法,这个方法会去检查__dict__里面会不会存在__iter__这个键,如果存在就返回True。

本文向读者讲解了如何面向接口编程,不去依赖具体的实现,实现依赖倒置。讲解了两种方式,强契约:基类继承,软契约:协议。

Read more

Flutter 组件 whitecodel_auto_link 适配鸿蒙 HarmonyOS 实战:交互式文本探针,构建信息流自动链接识别与极速预览架构

Flutter 组件 whitecodel_auto_link 适配鸿蒙 HarmonyOS 实战:交互式文本探针,构建信息流自动链接识别与极速预览架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 whitecodel_auto_link 适配鸿蒙 HarmonyOS 实战:交互式文本探针,构建信息流自动链接识别与极速预览架构 前言 在鸿蒙(OpenHarmony)生态迈向深度社交、企业办公及即时通讯全场景覆盖的背景下,如何将枯燥的长文本转化为具备可交互能力的“信息枢纽”,已成为提升用户操作效率的关键。在鸿蒙设备这类强调分布式协同与智慧感知的移动终端上,如果应用仅能显示纯文本,而无法识别其中的网址(URL)、邮箱(Email)或电话(Phone),用户就必须通过复杂的“长按、复制、切换应用、粘贴”链路来处理信息,这极大地割裂了鸿蒙系统的流转体验。 我们需要一种能够自动扫描文本特征、支持多维热点识别且具备高性能渲染能力的富文本处理引擎。 whitecodel_auto_link 为 Flutter 开发者引入了极其简便的长文本自动链接方案。它通过内置的高精度正则匹配矩阵,自动将文本中的特定识别域转化为可点击的高亮区域。在适配到鸿蒙

By Ne0inhk
Spring Boot 后端分层开发实战:从 MVC 到三层架构详解

Spring Boot 后端分层开发实战:从 MVC 到三层架构详解

应用分层 通过上面的练习,我们学习了 Spring MVC 简单功能的开发,但是我们也发现了一些问题。目前我们程序的代码有点 “杂乱”,然而当前只是 “一点点功能” 的开发。如果我们把整个项目功能完成呢?代码会更加的 “杂乱无章”(文件乱,代码内容乱)。 也基于此,咱们接下来学习应用分层。类似公司的组织架构:公司初创阶段,一个人身兼数职,既做财务,又做人事,还有行政。随着公司的逐渐壮大,会把岗位进行细分,划分为财务部门,人事部门,行政部门等。各个部门内部还会再进行细分。 项目开发也是类似,最开始功能简单时,我们前后端放在一起开发,随着项目功能的复杂,我们分为前端和后端不同的团队,甚至更细粒度的团队。后端开发也会根据功能再进行细分。MVC 就是其中的一种拆分方式。但是随着后端人员不再涉及前端,后端开发又有了新的分层方式。 4.1 介绍 阿里开发手册中,关于工程结构部分,定义了常见工程的应用分层结构: 那么什么是应用分层呢?应用分层是一种软件开发设计思想,

By Ne0inhk

大模型实习模拟面试面经:同花顺金融大模型算法一面深度复盘(RAG、LoRA、强化学习、Agent 架构全解析)

大模型实习模拟面试面经:同花顺金融大模型算法一面深度复盘(RAG、LoRA、强化学习、Agent 架构全解析) 关键词:大模型面试|RAG 重排序|LoRA 参数优化|GRPO 训练异常处理|Agentic RL|金融 Agent 开发|AI for SE 前言:为什么这场面试值得复盘? 2026 年,大模型技术已从“学术热点”全面转向“工业落地”,尤其在金融、医疗、法律等高价值垂直领域,智能 Agent 正成为企业核心竞争力的关键载体。作为国内领先的金融科技公司,同花顺近年来大力投入金融大模型与智能投研 Agent 的研发,其算法岗面试自然聚焦于工程实现能力 + 领域理解深度 + 技术前沿敏感度三大维度。 本文基于真实模拟面试场景,完整还原一场面向大模型算法实习生岗位的一轮技术面全过程。面试官围绕 RAG 重排序机制、LoRA

By Ne0inhk
Spring Cloud 熔断降级详解:用 “保险丝“ 类比,Sentinel 实战教程

Spring Cloud 熔断降级详解:用 “保险丝“ 类比,Sentinel 实战教程

欢迎文末添加好友交流,共同进步! “ 俺はモンキー・D・ルフィ。海贼王になる男だ!” * 📋 目录 * 什么是熔断降级 * 定义 * 为什么需要熔断降级? * 保险丝类比:形象理解熔断机制 * 生活中的保险丝 * 熔断器工作原理对比 * 熔断器三种状态 * Sentinel 核心概念 * 什么是 Sentinel? * 核心概念对比 * Sentinel vs Hystrix 对比 * Sentinel 实战教程 * 环境准备 * 1. 添加依赖 * 2. 配置文件 * 基础示例:注解方式 * 3. 主启动类 * 4. 创建订单服务 * 5. 控制器 * 高级配置:规则定义 * 6. 流控规则配置 * OpenFeign 集成 * 7. Feign客户端集成Sentinel * 8. Feign降级处理 * 规则持久化(

By Ne0inhk