Python类型检查:Literal[False]、overload和NoReturn。

7

我有以下(打印的)Python函数:

from typing import overload, Literal, NoReturn

@overload
def check(condition: Literal[False], msg: str) -> NoReturn:
    pass

@overload
def check(condition: Literal[True], msg: str) -> None:
    pass

def check(condition, msg):
    if not condition:
        raise Exception(msg)

Pyright类型检查器报错:

Overloaded function implementation is not consistent with signature of overload 1
  Function return type "NoReturn" is incompatible with type "None"
    Type cannot be assigned to type "None"

我对此感到困惑-- Pyright显然无法确定,如果条件为Falsecheck将总是抛出一个错误。我该如何修改使其正常工作?

为了上下文,这段代码通过了mypy的类型检查。 - Brian61354270
有趣,也许是个漏洞--我会发布到Pyright问题中。 - Sean Mackesey
1个回答

5

我在Pyright问题跟踪器上发布了这个问题,被告知必须在check实现中添加Union[NoReturn, None]注释以解决错误:

[这]是由于pyright的返回类型推断规则导致的。只有当所有代码路径都引发异常时,Pyright才会推断出NoReturn类型。某些代码路径引发异常很常见,如果在该情况下pyright将NoReturn包含在联合中,就会产生许多误报,因此在推断返回类型的联合中始终省略NoReturn。

Mypy没有任何返回类型推断的支持,这就解释了为什么这种情况不会发生在mypy中。

正确的注释方式是在实现中包括显式的None | NoReturn返回类型。

很不幸,这破坏了重载的初衷,即允许PyRight从参数推断出当返回类型为NoReturn时。我询问是否可以使用overload有条件地将NoReturn表达给类型检查器,但显然不行

不幸的是,由于其核心架构,pyright无法进行此类判断。代码流图中节点的“可达性”不能依赖于类型评估,因为类型评估取决于代码流节点的可达性。为了解决这个鸡生蛋的问题,确定可达性的逻辑会进行一些基本检查,以确定被调用的函数是否可能是“NoReturn”函数,但这些基本检查不足以处理重载评估。评估重载需要完整的类型评估器,而这取决于可达性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接