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

Mypy无法正确解析复合条件下的Union类型,求优化处理方案

解决mypy对复合条件下Union类型推导报错的问题

当mypy解析Union类型时,会通过代码流推导类型,如下代码可以正常通过mypy检查:

import typing as typ


def foo(x: typ.Union[int, None] = None, y: typ.Union[int, None] = None) -> int:
    if x is None and y is None:
        raise ValueError
    if x is None:
        x = 1
    if y is None:
        y = 2
    return x + y


foo(1, 2)

但当调整为复合条件(逻辑仍正确)时,mypy会报错:

import typing as typ


def foo(x: typ.Union[int, None] = None, y: typ.Union[int, None] = None) -> int:
    if x is None and y is None:
        raise ValueError
    if x is None and y is not None:
        x = 1
    if y is None and x is not None:
        y = 2
    return x + y


foo(1, 2)

报错信息:

main.py:15: error: Unsupported operand types for + ("int" and "None")
main.py:15: error: Unsupported operand types for + ("None" and "int")
main.py:15: error: Unsupported left operand type for + ("None")
main.py:15: note: Both left and right operands are unions
Found 3 errors in 1 file (checked 1 source file)

针对必须使用复合条件、不愿添加冗余代码的需求,以下是几种更优的处理方式:

1. 重构条件分支为互斥结构

将后续的if改为elif,让分支逻辑更清晰,帮助mypy完成类型推导:

import typing as typ


def foo(x: typ.Union[int, None] = None, y: typ.Union[int, None] = None) -> int:
    if x is None and y is None:
        raise ValueError
    elif x is None:
        # 此时y必然不为None(已被前面的条件排除)
        x = 1
    elif y is None:
        # 此时x必然不为None(已被前面的条件排除)
        y = 2
    return x + y

这种方式无需额外代码,通过优化分支逻辑让mypy自然识别变量类型,是最推荐的方案。

2. 使用assert辅助类型推导

在return前添加assert语句,既可以辅助mypy推导类型,又能保留运行时的逻辑校验(并非冗余代码):

import typing as typ


def foo(x: typ.Union[int, None] = None, y: typ.Union[int, None] = None) -> int:
    if x is None and y is None:
        raise ValueError
    if x is None and y is not None:
        x = 1
    if y is None and x is not None:
        y = 2
    # 断言x和y均不为None,帮助mypy推导类型
    assert x is not None and y is not None, "x或y不能为None"
    return x + y

assert在运行时会触发检查,若逻辑出错能及时发现,同时mypy会将其视为类型断言,认定后续x和y均为int类型。

3. 使用typing.cast强制类型标注

通过cast直接告知mypy变量的实际类型,绕过类型推导限制:

import typing as typ


def foo(x: typ.Union[int, None] = None, y: typ.Union[int, None] = None) -> int:
    if x is None and y is None:
        raise ValueError
    if x is None and y is not None:
        x = 1
    if y is None and x is not None:
        y = 2
    return typ.cast(int, x) + typ.cast(int, y)

注意:cast仅用于类型检查阶段,不会对实际运行时的变量做转换,因此必须确保逻辑上x和y此时确实不为None,否则会引发运行时错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 01:25:39