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

如何告知MyPy调用指定方法后变量不可能为None?

mypy自定义非空校验不生效问题解决方案

问题根因

mypy的类型窄化逻辑默认仅作用于当前作用域的直接判断,不会自动关联自定义校验方法的返回值和实例属性的类型状态,因此你通过IsDataValid方法做的判断无法让mypy识别到后续self.data不可能为None。

可行方案

方案1:使用TypeGuard标注校验方法(推荐)

这是最符合类型规范的方案,通过TypeGuard标注你的校验方法,明确告知mypy:当该方法返回True时,当前实例的data属性一定为str类型。
Python 3.11+可直接从标准库typing导入TypeGuard和Self,低版本Python需从typing-extensions导入对应类型。修改后的代码示例如下:

from typing import Optional, TypeGuard, Self

class Foo:
    data: Optional[str]

    def __init__(self):
        self.data = None

    def IsDataValid(self) -> TypeGuard[Self]:
        return self.data is not None

    def SetData(self, data: str) -> None:
        self.data = data

    def GetData(self) -> str:
        if not self.IsDataValid():
            raise ValueError("Invalid data")
        return self.data

方案2:增加显式窄化断言

如果不想修改原有校验方法的类型标注,可以在校验调用后加一行显式断言,仅用于mypy类型提示,同时也能做运行时二次校验:

def GetData(self) -> str:
    if not self.IsDataValid():
        raise ValueError("Invalid data")
    assert self.data is not None
    return self.data

该方案改动量极小,无需引入额外依赖,适合临时快速修复。

方案3:改造校验方法为直接抛错的工具方法

将返回布尔值的校验方法改为无效直接抛异常的形式,mypy会识别到只要方法正常返回,就说明data已经是有效状态:

def EnsureDataValid(self) -> None:
    if self.data is None:
        raise ValueError("Invalid data")

def GetData(self) -> str:
    self.EnsureDataValid()
    return self.data

该方案完全避免了后续重复编写抛错逻辑,适合多位置需要做合法校验的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:06:05