5

我有以下(键入)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 显然无法确定check如果条件为False. 我怎样才能按摩它以使其发挥作用?

4

1 回答 1

3

我将此发布到 Pyright 问题跟踪器,并被告知我必须向实现添加Union[NoReturn, None]注释以check解决错误:

[This] 不符合 pyright 的返回类型推断规则。只有在所有代码路径都引发异常的情况下,Pyright 才会推断出 NoReturn 类型。某些代码路径引发异常是很常见的,如果 pyright 在这种情况下将 NoReturn 包含在联合中,则会产生许多误报,因此在推断的返回类型中,NoReturn 总是从联合中省略。

Mypy 不支持返回类型推断,所以这就解释了为什么 mypy 不会发生这种情况。

对此进行注释的正确方法是包含一个明确的 None | NoReturn 实现的返回类型。

不幸的是,这首先破坏了重载的目的,即允许PyRight从参数推断NoReturn返回类型何时是。我问是否可以使用overloads 有条件地表达NoReturn给类型检查器。显然不是

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

于 2021-12-12T23:56:23.363 回答