Python自定义Mapping类__getitem__重载触发Pylance报错问题
错误根因
你遇到的Pylance报错核心是自定义的__getitem__重载违反了父类Mapping[PR, VA]的类型契约:
- 标准库
Mapping抽象基类定义的__getitem__签名固定为仅接收PR(键类型)的入参,返回VA(值类型) - 你新增的接收
Sequence[PR]返回List[VA]的重载,和父类签名不兼容,不符合里氏替换原则,因此被类型检查工具标记错误
解决方案
方案1:放弃继承Mapping,改用自定义Protocol适配行为
如果你不需要完全兼容Mapping的所有接口约定,可以自定义符合预期行为的Protocol,规避父类的签名约束:
from typing import TypeVar, Sequence, List, Protocol, overload PR = TypeVar('PR', bound=str) VA = TypeVar('VA') class NSProtocol(Protocol[PR, VA]): @overload def __getitem__(self, property: PR) -> VA: ... @overload def __getitem__(self, property: Sequence[PR]) -> List[VA]: ... # 补充其他你需要的Mapping类方法定义,比如__len__、__iter__等 class NS(NSProtocol[PR, VA]): @overload def __getitem__(self, property: PR) -> VA: ... @overload def __getitem__(self, property: Sequence[PR]) -> List[VA]: ... def __getitem__(self, property: PR|Sequence[PR]) -> VA|List[VA]: # 原有实现逻辑 ...
方案2:保留Mapping继承,新增独立方法实现批量获取
如果要严格遵守Mapping的接口约定,不要修改__getitem__的原生签名,额外增加批量取值的专用方法即可:
from typing import TypeVar, Mapping, Sequence, List PR = TypeVar('PR', bound=str) VA = TypeVar('VA') class NS(Mapping[PR, VA]): def __getitem__(self, property: PR) -> VA: # 原有单个取值逻辑 ... def get_many(self, properties: Sequence[PR]) -> List[VA]: # 批量取值逻辑 ... # 补充其他Mapping要求实现的方法:__len__、__iter__等
方案3:临时抑制报错(不推荐)
如果确认你的实现不存在类型安全问题,只是需要绕过Pylance检查,可以在报错行添加# type: ignore注释,该方案会损失对应代码的类型检查能力。
内容的提问来源于stack exchange,提问作者Dave Mcsavvy
相关产品推荐
相关产品推荐

