一个函数永远不会返回

问题描述:

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也不离开返回类型不确定,似乎在这些情况下是正确的。

即使“PEP 484 — Type Hints”标准提及问题和答案但没有人引用其涵盖您的问题的部分:The NoReturn type

报价:

typing模块提供一种特殊类型的NoReturn标注,从来没有正常返回的功能。例如,一个函数,它无条件地引发一个例外:

from typing import NoReturn 

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

该部分还提供了错误的用途的例子。尽管它没有涵盖无限循环的功能,但在类型理论中它们都同样满足从不会返回这个特殊类型表示的含义。

+1

Julian和我大概可以被原谅,因为在2016年7月我问这个问题时,在PEP 484中没有注意到'NoReturn'类型,因为它还没有存在,直到[几乎不会添加到PEP一年后](https://github.com/python/peps/commit/881c6bebdb79d3a51dea0a467e81abed410e5570)。不过,是的,这看起来像是现在的正确答案。 –

+0

哇!所以这个更新对于一个三年前的文档来说是相当新鲜的,但它缺少像[PEP 0](https://www.python.org/dev/peps/)中的“Last Modified”这样的标题。另外,现在它给了我一个暗示,为什么我的IDE不能从'输入'识别'NoReturn'类型,但在运行时却没有真正的问题。 – misanthrope

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

  • 当一个函数没有返回,没有返回值(甚至没有None)是一类能分到。所以你实际上并没有试图注解一个类型;您正在尝试注释缺少类型

  • 从Python 3.5版开始,类型暗示PEP只在标准中被采用。此外,PEP只建议看起来像什么类型的注释,而故意模糊如何使用它们。所以没有一个标准告诉我们如何做特别的事情,超越了这些例子。

  • 的PEP具有载明下列一段Acceptable type hints

    注解必须是没有在函数定义时引发异常评估有效表达式(但请参阅下面的向前引用)。

    注解应保持简单或静态分析工具可能无法解释值。例如,动态计算类型不太可能被理解。 (这是一个故意有些含糊的要求,具体包括和排除可能被添加到作为担保的情况下讨论这个PEP的未来版本。)

    所以它试图从做过于创造性的东西阻止你,就像抛出返回类型提示中的异常,以表示函数永不返回。

  • 关于例外,the PEP states the following

    没有语法列出明确地提出了异常建议。目前,该功能的唯一已知用例是文档化的,在这种情况下,建议将此信息放入文档字符串中。

  • 有上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') 
    

这两个建议都可以结合起来。