“void”函数中的 NoReturn 与 None - Python 3.6 中的类型注释

Posted

技术标签:

【中文标题】“void”函数中的 NoReturn 与 None - Python 3.6 中的类型注释【英文标题】:NoReturn vs. None in "void" functions - type annotations in Python 3.6 【发布时间】:2018-06-10 19:29:28 【问题描述】:

Python 3.6 支持类型注解,如:

def foo() -> int:
    return 42

但是当一个函数没有返回任何东西时应该使用什么? PEP484 示例大多使用None 作为返回类型,但也有来自typing 包的NoReturn 类型。

所以,问题是什么更可取,什么被认为是最佳实践:

def foo() -> None:
    #do smth

from typing import NoReturn

def foo() -> NoReturn:
    #do smth

【问题讨论】:

None的类型不是None,而是NoneType @Willem Van Onsem,根据 PEP484,None 在类型提示中被认为等同于 type(None) 什么是 NoneType 【参考方案1】:

NoReturn 表示函数从不返回值

函数要么不终止,要么总是抛出异常:"The typing module provides a special type NoReturn to annotate functions that never return normally. For example, a function that unconditionally raises an exception.."。

from typing import NoReturn

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

也就是说,x = foo_None() 类型有效但可疑,而 x = foo_NoReturn() 无效。

除了永远不会有可分配的结果外,NoReturn 在分支分析中还有其他含义:foo_NoReturn(); unreachable..。在'A NoReturn type is needed #165'票中有进一步的讨论。

为了执行分支分析,有必要知道哪些调用永远不会正常返回。例如sys.exit(总是通过异常返回)和os.exit(从不返回)..

【讨论】:

奇怪的是,对于一个可能抛出异常的函数,Optional[NoReturn] 没有传递 mypy(“错误:缺少返回语句”),即使该函数没有'不返回或返回None ...也许这与NoReturn也是底部类型有关 @joel: 因为,至少在概念上,NoReturn 本身不是一个类型,它表示 absense of type 因为有没有关联值,甚至没有None。它甚至不能分配,所以你可能不能(至少肯定不应该)在UnionTypeAlias 等中使用它。 @MestreLion 我不关注;类型不必具有值才能成为类型。 Idris 中的 Void 和 Scala 中的 Nothing 就是示例。我看不出你不应该在Union 中使用它的任何类型理论原因。当然它在 python 中不是很有用,但我认为它是有效的 @joel 没错,从概念上讲,类型不需要值。但是在f(...) -> type:注解的上下文中,我们指的是返回的类型。它有一个非常具体的含义,而不是一个函数退出的howwhenif 的一般注释。允许这样做需要更改 ->语义,如 PEP 所述

以上是关于“void”函数中的 NoReturn 与 None - Python 3.6 中的类型注释的主要内容,如果未能解决你的问题,请参考以下文章

noreturn 的意义何在?

__attribute__((noreturn))的用法

使用 Void 的实际例子

warning: control reaches end of non-void function

Linux C语言编译警告:control reaches end of non-void function

DllImport Unmanaged, Non .NET Dll to .NET Project 表示 Char * 和 Void __StdCall