You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 09:35:16