移除返回类型Any后Pyright报错:所有代码路径需返回int类型
解决Pyright返回类型检查报错问题
报错原因
Pyright无法确认Exp类的所有子类都被match语句覆盖,默认认为存在未处理的代码分支,会返回None,与你声明的int返回类型冲突——哪怕你实际没有定义其他Exp子类,类型检查器也无法静态推断这一点。
解决方案
方案1:标记Exp为密封类(推荐)
利用Pyright支持的@sealed装饰器(对应你提到的PEP草案),明确告知类型检查器Exp的所有子类都已在当前代码中定义,不存在其他子类。
需要先导入sealed:
- Python 3.12+:从
typing导入 - 旧版本:从
typing_extensions导入
修改后的代码:
from dataclasses import dataclass # Python 3.12+用下面这行,否则替换为 from typing_extensions import sealed from typing import sealed @sealed class Exp: pass @dataclass class Const(Exp): value: int @dataclass class Negate(Exp): value: Exp @dataclass class Add(Exp): value1: Exp value2: Exp @dataclass class Multiply(Exp): value1: Exp value2: Exp def eval_exp_old(e: Exp) -> int: match e: case Const(i): return i case Negate(e2): return -eval_exp_old(e2) case Add(e1, e2): return eval_exp_old(e1) + eval_exp_old(e2) case Multiply(e1, e2): return eval_exp_old(e1) * eval_exp_old(e2)
方案2:添加兜底分支抛出异常
如果不想使用密封类,可以在match语句末尾添加一个兜底分支,直接抛出异常,确保所有代码路径要么返回int,要么终止执行(不会返回None)。
修改后的函数:
def eval_exp_old(e: Exp) -> int: match e: case Const(i): return i case Negate(e2): return -eval_exp_old(e2) case Add(e1, e2): return eval_exp_old(e1) + eval_exp_old(e2) case Multiply(e1, e2): return eval_exp_old(e1) * eval_exp_old(e2) case _: raise ValueError(f"Unsupported Exp type: {type(e).__name__}")
补充说明
你原来的返回类型int | Any是冗余的,因为所有分支都明确返回int,直接声明-> int即可。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

