讲师中心 微信公众号

工具推荐

视频效率加速
立刻MV
立刻MV

低成本歌曲 MV、视频生成

剧云
剧云

中文短剧剧本制作平台

Laper
Laper

剧本策划到成片协作

AniShort
AniShort

AI短剧协同制作平台

Python 如何用 typing.Protocol 定义“鸭子类型”接口

雨敏酱_4298

雨敏酱_4298

发布时间:2026-01-23 20:48:10

|

1014人浏览过

|

来源于php中文网

原创

typing.Protocol 是结构类型检查机制,仅在静态类型检查时生效,不生成运行时对象,也不参与 isinstance 或 issubclass 判断;需用 @runtime_checkable 才支持运行时结构校验。

python 如何用 typing.protocol 定义“鸭子类型”接口

typing.Protocol 本质是结构类型检查,不是运行时接口

Python 的 Protocol 不会生成运行时对象,也不参与 isinstance 或 issubclass 判断——它只在类型检查器(如 mypy、pyright)中生效。如果你期望用 isinstance(obj, MyProtocol) 来做运行时鸭子类型校验,会直接报错:TypeError: isinstance() argument 2 cannot be a parameterized generic。

常见误用场景:把 Protocol 当成抽象基类(ABC)来用,结果运行时报错或类型检查不触发。关键区别在于:Protocol 关注“有没有这些方法”,ABC 关注“是不是这个类型”。

  • 要运行时检查鸭子类型,得自己写 hasattr + callable 组合,或用 collections.abc 中的现成 ABC(如 Iterable)
  • 要让 mypy 报错,必须开启类型检查(例如命令行加 --strict),否则 Protocol 形同虚设
  • 定义带泛型的 Protocol 时,必须继承 Generic[T],且不能漏掉 __parameters__ 的隐式推导逻辑

定义最小可行 Protocol:只声明方法签名,不写实现

Protocol 类里只允许出现方法签名、属性注解、类变量(带默认值的常量),禁止任何方法体、self 参数的具体类型标注(除非是泛型绑定)、__init__ 实现等。否则 mypy 会警告 Protocol cannot have non-method members。

例如想约束“能被 len() 调用且支持索引”的对象:

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

from typing import Protocol
<p>class SizedIndexable(Protocol):
def <strong>len</strong>(self) -> int: ...
def <strong>getitem</strong>(self, i: int) -> str: ...

注意三点:

Python Hardener
Python Hardener

通过完整的安全审查、代码整洁重构、健壮的错误处理、正确的日志记录以及完整的文档字符串覆盖,强化 Python 脚本。

下载
  • 方法末尾必须加 ...(省略号),这是语法强制要求,表示无实现
  • 返回类型必须明确,不能留空或写 pass
  • 如果方法接受泛型参数(如 T),需在类头声明 class MyProto(Protocol, Generic[T]):

Protocol 和 ABC 混用:用 @runtime_checkable 让 isinstance 生效

标准库的 typing.runtime_checkable 装饰器可以让某个 Protocol 支持运行时 isinstance 检查,但仅限于“结构匹配”——即对象动态拥有所有声明的方法/属性,且它们是可调用的。

示例:

from typing import Protocol, runtime_checkable
<p>@runtime_checkable
class Readable(Protocol):
def read(self, size: int = -1) -> bytes: ...</p><p>class FakeFile:
def read(self, size: int = -1) -> bytes:
return b"hello"</p><p>assert isinstance(FakeFile(), Readable)  # ✅ 成立

但要注意:

  • @runtime_checkable 不检查方法签名是否一致(比如参数名、默认值、返回类型),只检查存在性和可调用性
  • 若对象的 read 方法实际接收 **kwargs,isinstance 仍返回 True,但类型检查器可能报错
  • 装饰后无法再继承其他 Protocol(mypy 限制),多继承需谨慎

Protocol 常见陷阱:__init__、属性赋值、可变默认参数

很多人试图在 Protocol 中定义 __init__ 来约束构造方式,这是无效的——Protocol 不控制实例化过程。同样,给属性赋值(如 name: str = "default")会被视为实例变量,而非类型契约的一部分,容易误导。

真正该关注的是“调用后行为”,比如:

  • 需要对象有 .name 属性并可读?写 name: str(只注解,不赋值)
  • 需要对象有 .name 并可写?得额外声明 name: str 和 @name.setter 方法签名
  • 需要兼容 dataclass 或 NamedTuple?确保字段名和类型完全一致,否则 mypy 可能不认为其满足协议
  • 用了可变默认参数(如 def append(self, items: list = []))?类型检查器会按字面理解,但运行时风险得靠代码规范规避

最易被忽略的一点:Protocol 的成员访问是“宽泛匹配”。哪怕一个类只实现了协议中 1 个方法,mypy 默认也不会报错——除非你显式标注变量类型为该 Protocol,并尝试调用未实现的方法。

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6384

2023.10.24

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6384

2023.10.24

java多继承如何实现
java多继承如何实现

本专题整合了java多继承相关内容以及教程,阅读专题下面的文章了解更多详细内容。

458

2025.10.28

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

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

3248

2023.10.19

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

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

5469

2025.10.17

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

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

3909

2025.12.29

java接口相关教程
java接口相关教程

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

506

2026.01.19

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

4616

2024.01.03

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

热门下载

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

精品课程

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn