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

如何在子类中向mypy声明属性不可为None?

问题描述

现有如下代码:

from dataclasses import dataclass

@dataclass
class MaybeTextContainer:
    text: list[str] | None


class CertainlyText(MaybeTextContainer):
    def __init__(self) -> None:
        super().__init__(text=[])
        self.say_hi()

    def say_hi(self) -> None:
        self.text.append("Hi")

运行mypy时,最后一行会报错:error: Item "None" of "list[str] | None" has no attribute "append"。

虽然可以在say_hi函数中添加assert self.text来解决,但如果多个函数都要修改self.text,这种方式过于繁琐。想知道有没有通用方法可以向mypy表明子类中的self.text属性不可为None?


解决方案

方法一:子类中重新注解属性类型

直接在子类里重新声明text属性,将类型明确为list[str],mypy会认可子类的类型覆盖:

from dataclasses import dataclass

@dataclass
class MaybeTextContainer:
    text: list[str] | None


class CertainlyText(MaybeTextContainer):
    text: list[str]  # 重新注解,指定属性不可为None

    def __init__(self) -> None:
        super().__init__(text=[])
        self.say_hi()

    def say_hi(self) -> None:
        self.text.append("Hi")  # mypy不再报错

注意:必须保证子类初始化逻辑确实给text赋值了非None值,避免运行时出现异常。

方法二:使用泛型构建灵活基类

如果有多个类似场景,可通过泛型定义基类,让子类指定具体的属性类型:

from dataclasses import dataclass
from typing import TypeVar, Generic

T = TypeVar("T")

@dataclass
class TextContainer(Generic[T]):
    text: T


class MaybeTextContainer(TextContainer[list[str] | None]):
    pass


class CertainlyText(TextContainer[list[str]]):
    def __init__(self) -> None:
        super().__init__(text=[])
        self.say_hi()

    def say_hi(self) -> None:
        self.text.append("Hi")

这种方式能清晰区分不同子类的属性约束,扩展性更强。

方法三:初始化时统一类型转换

在子类的__init__方法中,用cast明确告知mypyself.text的实际类型,后续所有方法均可直接使用:

from dataclasses import dataclass
from typing import cast

@dataclass
class MaybeTextContainer:
    text: list[str] | None


class CertainlyText(MaybeTextContainer):
    def __init__(self) -> None:
        super().__init__(text=[])
        self.text = cast(list[str], self.text)  # 统一做类型注解转换
        self.say_hi()

    def say_hi(self) -> None:
        self.text.append("Hi")  # mypy不再报错

这种方式无需重新声明属性,仅需在初始化阶段做一次类型断言即可。


内容的提问来源于stack exchange,提问作者Frank Meulenaar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:05:18