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

如何修复mypy报错:赋值表达式类型Optional[str]与变量str不兼容

mypy类型不兼容错误排查与解决

问题描述

遇到mypy类型不兼容错误,报错信息:

error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str")

对应代码如下:

def func(
    a: int | None = None,
    b: str | None = None,
):
    if not (a or b):
        b = "string"
    elif a:
        b = str(a)
    c: str = b
    return type(c)

实际运行时,无论怎么调用func,c都不会是None,以下断言均可验证:

assert func() == str
assert func(a=1) == str
assert func(b="2") == str
assert func(a=3, b="4") == str

想明确两个问题:为什么mypy会报错?如何在不添加以下冗余代码的前提下让mypy认可代码正确性?

if b is None:
    raise RuntimeError

为什么mypy报错?

mypy的类型分析基于静态代码逻辑推导,而非运行时实际行为。你的代码里,if not (a or b)和elif a两个分支只覆盖了部分场景,但mypy无法自动推导剩余场景下b一定不为None:

  • 当a为None且b是合法字符串时,not (a or b)为False,elif a也为False,代码会直接跳过两个分支执行c: str = b。虽然运行时b确实是str,但mypy只看到b的声明类型是str | None,且没有显式分支确保此时b非空,因此判定类型不兼容。

解决方案

有几种简洁方式可以让mypy认可代码逻辑:

1. 用断言明确b的非空性

在赋值前添加断言,既保留运行时安全检查,又给mypy明确的类型提示:

def func(
    a: int | None = None,
    b: str | None = None,
):
    if not (a or b):
        b = "string"
    elif a:
        b = str(a)
    assert b is not None, "b should never be None here"
    c: str = b
    return type(c)

2. 优化分支逻辑,覆盖所有路径

调整条件判断,让mypy能清晰看到所有路径下b都会被赋值为非None:

def func(
    a: int | None = None,
    b: str | None = None,
):
    if not b:
        b = str(a) if a is not None else "string"
    c: str = b
    return type(c)

这里先判断b是否为空(包括None和空字符串),为空时直接根据a的值赋值,确保所有路径下b最终都是str类型,mypy可直接推导。

3. 使用cast强制转换类型

如果能100%确定运行时b不为None,可以用cast给mypy明确类型提示(仅编译期生效,无运行时检查):

from typing import cast

def func(
    a: int | None = None,
    b: str | None = None,
):
    if not (a or b):
        b = "string"
    elif a:
        b = str(a)
    c: str = cast(str, b)
    return type(c)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 11:10:33