Python:基类与派生类的列表订阅类型解析及类型检查问题
类型检查器兼容性与泛型可变性问题
背景
我正在开发一款服务于化学研究组的Python数据管理库,核心定义了Dataset类,包含CharacterizationMethod、RawData等基类,供用户继承创建适配自身研究的类,继承的属性与方法确保用户类可兼容库内工具。
当前遇到用户自定义类的函数参数类型标注问题,示例代码如下:
from dataclasses import dataclass, field @dataclass class BaseComponent: name: str = "" @dataclass class BaseParent: components: list[BaseComponent] = field(default_factory=list) @dataclass class UserComponent(BaseComponent): pass @dataclass class UserParent(BaseParent): pass user_component = UserComponent() user_components = [user_component, user_component] user_parent1 = UserParent(components=[user_component]) # ok user_parent2 = UserParent(components=user_components) # not ok user_parent3 = UserParent(components=[*user_components]) # ok def create_user_parent1(component: UserComponent) -> UserParent: return UserParent(components=[component]) # ok def create_user_parent2(components: list[UserComponent]) -> UserParent: return UserParent(components=components) # not ok def create_user_parent3(components: list[UserComponent]) -> UserParent: return UserParent(components=[*components]) # ok
注释标注了VS Code中pylance类型检查器的报错位置。相关讨论显示这与list类型参数的不变性有关,将基类属性改为Sequence[T]可解决该类型问题,但会引发其他依赖list[T]的方法报错。需注意此问题仅出现在pylance中,使用mypy检查上述代码无报错。
学习疑问
- 为何pylance对示例中看似等价的参数处理不同
- 为何pylance与mypy的类型分析结果不一致
- 为何pylance中可变泛型类型(如
list)参数为不变性,而不可变泛型类型(如Sequence)参数为协变性
实际需求问题
想确认这是否属于架构问题的代码异味,另一种方案是使用带@runtime_checkable装饰器的Protocol类定义接口,但最初尝试时每个类(如CharacterizationMethod)需同时定义Protocol接口和mixin模板类,存在冗余性。
内容的提问来源于stack exchange,提问作者pbPy
相关产品推荐
相关产品推荐

