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

为何mypy无法推断a or b非None类型?如何解决?

MyPy类型推断问题:a or b在断言后仍被推断为包含None

我们有如下代码,从逻辑上看,只要a或b其中一个不为None,a or b就不可能是None:

a: int | None
b: int | None
assert (a is not None) or (b is not None)
reveal_type(a or b)

但MyPy输出的推断结果却是:

main.py:4: note: Revealed type is "Union[builtins.int, None]"

问题原因

  • MyPy的类型分析不会将断言的逻辑条件与后续or表达式的类型推断关联起来。它单独处理a or b时,只会基于a和b本身的int | None类型,得出返回值可能为None的结论,无法从(a is not None) or (b is not None)这个断言中推导排除None的可能。
  • 本质是MyPy的数据流分析在这种跨表达式的逻辑约束场景下,没有做足够深入的推导。

解决方法

方法1:用条件分支显式窄化类型

通过分情况处理,让MyPy明确知道每个分支里变量的非None状态:

a: int | None
b: int | None
assert (a is not None) or (b is not None)

if a is not None:
    result = a
else:
    result = b  # MyPy此时能推断b必然不为None
reveal_type(result)  # 输出:Revealed type is "builtins.int"

方法2:使用辅助函数封装逻辑

借助函数的类型注解和断言,让MyPy正确推导返回值类型:

from typing import TypeVar, Optional

T = TypeVar('T')

def non_none_or(a: Optional[T], b: Optional[T]) -> T:
    assert a is not None or b is not None
    return a or b

a: int | None
b: int | None
assert (a is not None) or (b is not None)
reveal_type(non_none_or(a, b))  # 输出:Revealed type is "builtins.int"

方法3:使用cast强制类型转换(不推荐)

如果不想修改代码结构,可以用cast直接指定类型,但这会绕过MyPy的类型检查,存在风险:

from typing import cast

a: int | None
b: int | None
assert (a is not None) or (b is not None)
reveal_type(cast(int, a or b))  # 输出:Revealed type is "builtins.int"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 00:45:49