新闻中心
Mypy 在 isinstance 中处理联合类型别名的已知问题

本文探讨了 mypy 在 `isinstance` 运行时类型检查中,当使用 `@runtime_checkable` 协议的联合类型别名时出现的类型错误。尽管涉及的协议并非参数化泛型,mypy 仍会报告“parameterized generics cannot be used in instance checks”错误。文章通过代码示例对比了报错与正常情况,揭示了此问题是 mypy 的一个已知 bug,并提供了临时的规避方法,以帮助开发者在使用 python 类型提示时避免此类困扰。
理解 Python 中的 Protocol 与 runtime_checkable
在 Python 中,Protocol 提供了一种结构化子类型(Structural Subtyping)的方式,允许我们定义一个接口,而不必通过继承来实现。任何类,只要实现了 Protocol 中定义的所有方法,就被认为是该 Protocol 的一个实现。
@runtime_checkable 装饰器则进一步增强了 Protocol 的功能,使得这些协议可以在运行时被 isinstance() 和 issubclass() 函数检查。这意味着我们可以像检查普通类一样,检查一个对象是否符合某个 Protocol 的结构。例如,typing 模块中的 SupportsInt、SupportsIndex 等都是 @runtime_checkable 的协议,用于检查对象是否支持转换为整数或索引。
Mypy 在 isinstance 中处理联合类型别名的限制
在使用 Mypy 进行静态类型检查时,开发者可能会遇到一个特定问题:当尝试在 isinstance() 检查中使用一个由多个 @runtime_checkable 协议组成的联合类型别名时,Mypy 会报告一个错误。
考虑以下场景,我们定义一个自定义的 SupportsTrunc 协议,并将其与 SupportsInt、SupportsIndex 组合成一个联合类型别名 _ConvertibleToInt:
from typing import Protocol, runtime_checkable, SupportsIndex, SupportsInt
@runtime_checkable
class SupportsTrunc(Protocol):
def __trunc__(self) -> int:
...
# 定义一个联合类型别名
_ConvertibleToInt = SupportsInt | SupportsIndex | SupportsTrunc
def process_int_convertible(o: object) -> None:
if isinstance(o, _ConvertibleToInt):
# Mypy 报错:
# error: Parameterized generics cannot be used with class or instance checks
# error: Argument 2 to "isinstance" has incompatible type "<typing special form>"; expected "_ClassInfo"
print(f"Object {o} is convertible to int.")
else:
print(f"Object {o} is not convertible to int.")
# 示例使用
process_int_convertible(10)
process_int_convertible(3.14)
process_int_convertible("hello")尽管 SupportsInt、SupportsIndex 和 SupportsTrunc 都是 @runtime_checkable 协议,并且它们本身并非参数化泛型(如 list[int]),Mypy 仍然会抛出错误,提示“Parameterized generics cannot be used with class or instance checks”。这个错误令人困惑,因为它暗示我们正在使用泛型类型,而实际上并没有。
问题分析与示例对比
为了更好地理解这个问题,我们通过对比不同场景下的 Mypy 行为来分析:
-
直接使用联合类型(不使用别名)
如果我们在 isinstance 检查中直接使用联合类型,而不是通过类型别名,Mypy 不会报错:
from typing import SupportsIndex, SupportsInt def process_direct_union(o: object) -> None: if isinstance(o, SupportsInt | SupportsIndex): # Mypy 检查通过 print(f"Object {o} supports int or index conversion.") -
使用单个协议的类型别名
如果类型别名只指向一个 @runtime_checkable 协议,Mypy 也不会报错:
PHP轻论坛
简介PHP轻论坛是一个简单易用的PHP论坛程序,适合小型社区和个人网站使用。v3.0版本是完全重构的版本,解决了之前版本中的所有已知问题,特别是MySQL保留字
冲突问题。主要特点• 简单易用:简洁的界面,易于安装和使用• 响应式设计:适配各种设备,包括手机和平板• 安全可靠:避免使用MySQL保留字,防止SQL注入• 功能完善:支持分类、主题、回复、用户管理等基本功能• 易于扩展:模块化设计,便于
26
查看详情
from typing import SupportsInt _SingleConvertibleToInt = SupportsInt def process_single_alias(o: object) -> None: if isinstance(o, _SingleConvertibleToInt): # Mypy 检查通过 print(f"Object {o} supports int conversion.") -
使用重复协议的联合类型别名
即使联合类型别名中包含的是同一个协议的重复,Mypy 仍然会报错,这进一步表明问题出在“联合类型别名”这一结构上,而非协议的复杂性:
from typing import SupportsInt _DuplicateConvertibleToInt = SupportsInt | SupportsInt def process_duplicate_alias(o: object) -> None: if isinstance(o, _DuplicateConvertibleToInt): # Mypy 报错 print(f"Object {o} supports int conversion (via duplicate alias).")
通过上述示例对比,我们可以明确:Mypy 的错误并非源于 Protocol 本身的参数化,而是其在处理由多个 @runtime_checkable 协议组成的“联合类型别名”作为 isinstance 的第二个参数时,存在一个内部识别问题。
根本原因与解决方案
根据 Mypy 社区的反馈,这被确认为 Mypy 的一个已知 bug(例如,在 GitHub issue mypy/#16707 中有相关讨论)。Mypy 在解析 isinstance() 的第二个参数时,对于由 Union 类型别名构成的 @runtime_checkable 集合,未能正确识别其运行时可检查性,从而错误地将其视为“参数化泛型”。
当前的规避方法:
鉴于这是一个 Mypy 的 bug,最直接的规避方法是避免在 isinstance() 检查中使用由多个 @runtime_checkable 协议组成的类型别名。
你可以选择以下两种方式:
-
直接在 isinstance() 中写出联合类型:
from typing import SupportsIndex, SupportsInt, Protocol, runtime_checkable @runtime_checkable class SupportsTrunc(Protocol): def __trunc__(self) -> int: ... def process_object(o: object) -> None: # 直接使用联合类型,避免别名 if isinstance(o, SupportsInt | SupportsIndex | SupportsTrunc): print(f"Object {o} is convertible to int.") else: print(f"Object {o} is not convertible to int.") 如果类型别名是必要的,可以考虑在 isinstance 检查时将其展开(虽然这在代码中可能显得冗余,但可以规避 Mypy 错误): 这种方法在Python运行时并不直接支持,因为isinstance的第二个参数期望的是一个类或类的元组。因此,第一种方法是更实际和推荐的。
总结
Mypy 在 isinstance 检查中对 @runtime_checkable 协议的联合类型别名处理不当,是一个已知的静态分析工具限制。虽然这可能会给依赖类型别名来提高代码可读性的开发者带来不便,但通过直接在 isinstance 调用中写出联合类型,可以有效规避此问题。随着 Mypy 的不断发展和完善,我们期待这个 bug 能在未来的版本中得到修复,从而提供更灵活、更符合直觉的类型检查体验。在当前阶段,理解这一限制并采用相应的规避策略,是确保代码能够通过 Mypy 检查的关键。
以上就是Mypy 在 isinstance 中处理联合类型别名的已知问题的详细内容,更多请关注其它相关文章!
# 子类
# 前后端分离和seo
# 阿勒泰抖音关键词排名广告营销
# 邢台专业网站建设口碑好
# 烤鸭推广营销话术技巧
# 眉山小企业网站优化设计
# 葫芦岛网站优化如何办理
# 江苏天猫网站建设行业
# 成都seo优化价格低
# Seo除了代码优化还有
# 营销推广能力阐述的内容
# 易用
# 我们可以
# python
# 这一
# 是一个
# 都是
# 的是
# 第二个
# 多个
# 报错
# 代码可读性
# 工具
# github
# git
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
Python中高效访问嵌套字典与列表中的键值对
CSS Flexbox与媒体查询:实现响应式布局中元素的并排与堆叠
PHP表单数据传递:如何通过隐藏输入字段获取动态ID
Flexbox布局实践:实现粘性导航栏与底部固定页脚
使用 Pandas 高效处理 .dat 文件:数据清洗与数值计算实战
Golang如何优化CPU绑定任务分配策略_Golang CPU任务分配优化实践
蓝湖怎样用切图标注提对接效率_蓝湖用切图标注提对接效率【设计对接】
poki网页游戏推荐_poki免费游戏平台入口
win11专注助手在哪 Win11免打扰模式设置与自动化规则【指南】
CSS Box Model与弹性按钮:维持布局稳定的动画实践
J*aScript实现动态背景色下的文本与按钮颜色自适应调整
Centos/Linux 系统下安装 composer 的完整步骤
向日葵客户端怎么进行远程CentOS控制_向日葵客户端远程CentOS控制操作教程
快手极速版在线观看 官方网页版登录地址
AI泡沫首次被“刺破”:GPU十年都无法存活!
QQ官网正版登录链接 QQ在线登录入口最新
抖音怎么赚钱_抖音创作者变现方法与途径指南
漫蛙Manwa2官网入口地址分享 漫蛙漫画PC版永久访问通道
C++如何检测键盘输入_C++ _kbhit与_getch函数非阻塞输入
Django表单提交验证失败后保持字段值不刷新
在哪找SublimeJ远程工具_SFTP插件配置教程
12306几点到几点不能订票? | 官方最新系统维护时间全解析
Django模型中自动计算可用余额的实现方法
夸克AO3官网入口_AO3镜像网站2025推荐
yy漫画网页版官方入口_yy漫画官网登录页面链接
深入理解J*a编译器的兼容性选项:从-source到--release
CSS布局:解决全屏元素100%尺寸与外边距导致的页面溢出问题
Promise错误处理:在catch后终止链式then执行的策略
Win11怎么关闭快速启动_Win11彻底关机设置教程
PDF怎么合并PDF并保持格式_PDF合并文件保持排版教程
Yandex官网搜索引擎免登录_俄罗斯Yandex一键直达入口
必由学官网入口 必由学教师登录入口
在命令行怎么运行html项目_命令行运行html项目方法【教程】
如何使用CaptainHook和Composer管理Git钩子_在提交前自动运行代码检查的Composer配置
怎样把文件彻底粉碎无法恢复_Windows下安全删除敏感数据【隐私保护】
在J*a项目里如何构建对象之间的契约_接口约束的实际落地
qq邮箱日历功能怎么用_创建日程与会议邀请的技巧
微信网页版官方入口教程 微信网页版网页版快速登录步骤
深入理解J*a合成构造器:何时以及为何阻止其生成
Win10自动更新怎么关闭 Win10永久关闭系统更新的两种方法【终极版】
谷歌学术网站直达地址 谷歌学术搜索网页版一键进入
composer 和 npm/yarn 在管理依赖方面有什么核心思想差异?
怎样在Excel中做仪表盘_Excel仪表盘设计与关键指标展示方法
如何使 Jest 模拟函数默认抛出错误以提高测试效率
qq游戏免费畅玩入口_qq游戏电脑版快速启动
Go语言中高效处理x-www-form-urlencoded表单数据
解决Django多数据库/多Schema环境下外键迁移问题
快手赚钱渠道_快手收益来源
Python实现多节点属性重叠度分析教程
Composer的 "conflict" 字段有什么用_如何声明不兼容的包以避免依赖冲突


2025-11-09
浏览次数:次
返回列表
冲突问题。主要特点• 简单易用:简洁的界面,易于安装和使用• 响应式设计:适配各种设备,包括手机和平板• 安全可靠:避免使用MySQL保留字,防止SQL注入• 功能完善:支持分类、主题、回复、用户管理等基本功能• 易于扩展:模块化设计,便于