如何修复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
相关产品推荐
相关产品推荐

