【问题标题】:Python type-checking: Literal[False], overload, and NoReturnPython 类型检查:Literal[False]、重载和 NoReturn
【发布时间】:2021-12-12 20:38:16
【问题描述】:

我有以下(键入的)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 的类型检查。
  • 有趣,也许这是一个错误——我将发布到 Pyright 问题。

标签: python pyright


【解决方案1】:

我将此发布到 Pyright 问题跟踪器并且是 informed,我必须在 check 实现中添加 Union[NoReturn, None] 注释以解决错误:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多