Mypy中继承__init__时的Self类型收窄问题求助
泛型树形节点的类型标注正确姿势
这不是Mypy的bug,是你对泛型类的使用方式存在误区。
问题根源
你之前仅在__init__方法里用self: T标注类型,但没有将基类声明为泛型类,导致类属性的类型无法和子类的具体类型绑定,Mypy自然无法正确收窄类型。
正确实现方案
用TypeVar绑定基类,将基类定义为泛型类,子类继承时显式指定自身作为泛型参数,就能让属性类型自动关联到子类类型:
from typing import TypeVar, Generic, Optional, Sequence # 定义绑定到Node的TypeVar T = TypeVar('T', bound='Node') # 将Node声明为泛型类 class Node(Generic[T]): def __init__(self, parent: Optional[T] = None, children: Optional[Sequence[T]] = None) -> None: self.parent: Optional[T] = parent self.children: Optional[Sequence[T]] = children # 子类继承时指定自身为泛型参数 class SpecialNode(Node['SpecialNode']): pass # 测试函数 def process_children(children: Sequence[SpecialNode]) -> None: pass sn = SpecialNode() if sn.children is not None: process_children(sn.children) # Mypy可正确识别类型,无报错
关键要点
- 基类必须声明为
Generic[T],让类本身携带泛型参数,这样parent、children的类型会和类的泛型参数绑定。 - 子类继承时显式传入自身作为泛型参数,Mypy就能自动推导出子类实例的属性类型为
Optional[SpecialNode]和Optional[Sequence[SpecialNode]]。
Python 3.11+ 简化写法
如果使用Python 3.11及以上版本,可以直接用Self类型,无需手动声明泛型,写法更简洁直观:
from typing import Self, Optional, Sequence class Node: def __init__(self, parent: Optional[Self] = None, children: Optional[Sequence[Self]] = None) -> None: self.parent: Optional[Self] = parent self.children: Optional[Sequence[Self]] = children class SpecialNode(Node): pass def process_children(children: Sequence[SpecialNode]) -> None: pass sn = SpecialNode() if sn.children is not None: process_children(sn.children) # 类型识别正常
内容的提问来源于stack exchange,提问作者edik_
相关产品推荐
相关产品推荐

