键入一个函数永远不会返回的提示

时间:2016-07-25 14:14:47

标签: python type-hinting

Python的新type hinting功能允许我们输入函数返回None的提示......

def some_func() -> None:
    pass

...或者保留未指定的返回类型,PEP指示应该使静态分析器假设任何返回类型都是可能的:

  

任何没有注释的函数都应被视为具有最常用的类型

但是,我应该如何键入一个函数永远不会返回的提示?例如,键入提示这两个函数的返回值的正确方法是什么?

def loop_forever():
    while True:
        print('This function never returns because it loops forever')

def always_explode():
    raise Exception('This function never returns because it always raises')

在这些情况下,既未指定-> None也未指定未指定的返回类型似乎是正确的。

2 个答案:

答案 0 :(得分:6)

尽管“PEP 484 — Type Hints”标准提到了相关问题和答案,但没有人引用它的部分:The NoReturn type来涵盖您的问题。

引用:

  

typing模块提供了一个特殊类型NoReturn来注释永远不会正常返回的函数。例如,一个无条件地引发异常的函数:

from typing import NoReturn

def stop() -> NoReturn:
    raise RuntimeError('no way')

该部分还提供了错误用法的示例。虽然它没有涵盖具有无限循环的函数,但在类型理论中它们同样满足永远不会返回由该特殊类型表示的含义。

答案 1 :(得分:2)

2016年7月,此问题尚无答案(现在有NoReturn;请参阅the new accepted answer)。这些是一些原因:

  • 当函数没有返回时,没有可以分配类型的返回值(甚至不是None)。所以你实际上并没有试图注释一个类型;您试图注释缺少类型

  • 从Python 3.5版开始,标准中只采用了类型提示PEP。此外,PEP仅建议注释应该的类型,而在如何使用时故意模糊。因此,除了示例之外,没有标准告诉我们如何做任何特别的事情。

  • PEP有一个Acceptable type hints部分说明如下:

      

    注释必须是有效的表达式,在定义函数时不会引发异常进行求值(但请参阅下面的前向引用)。

         

    注释应保持简单,否则静态分析工具可能无法解释这些值。例如,不太可能理解动态计算的类型。 (这是一个有意模糊的要求,如本讨论所要求的那样,可以在本PEP的未来版本中添加特定的包含和排除。)

    所以它试图阻止你做过度创造性的事情,比如在返回类型提示中抛出一个异常,以表示函数永远不会返回。

  • 关于例外,the PEP states the following

      

    没有提出列出明确引发的异常的语法。目前,此功能的唯一已知用例是documentational,在这种情况下,建议将此信息放在docstring中。

  • type comments有一个建议,你有更多的自由,但即使是那个部分也没有讨论如何记录缺少某种类型。

当你想提示某些参数或某些"正常"的返回值时,有一件事你可以尝试稍微不同的情况。函数应该是一个永不返回的可调用函数。 syntaxCallable[[ArgTypes...] ReturnType],因此您可以省略返回类型,如Callable[[ArgTypes...]]中所示。但是,这并不符合推荐的语法,因此严格来说,它不是可接受的类型提示。类型检查员可能会窒息它。

结论:你超前于时间。这可能会令人失望,但对您来说也有一个优势:您仍然可以影响非返回功能应该如何注释。也许这将成为您参与标准化过程的借口。 : - )

我有两个建议。

  1. 允许在Callable提示中省略返回类型,允许向前提示任何类型的内容。这将导致以下语法:

    always_explode: Callable[[]]
    def always_explode():
        raise Exception('This function never returns because it always raises')
    
  2. 介绍bottom type like in Haskell

    def always_explode() -> ⊥:
        raise Exception('This function never returns because it always raises')
    
  3. 这两项建议可以合并。