为什么我们应该在 def __init__(self, n) -> None: 中使用 ->

Why should we use -> in def __init__(self, n) -> None:?

为什么要在def __init__(self, n) -> None:中使用->?我阅读了以下摘录 from PEP 484,但我无法理解其含义。

(Note that the return type of __init__ ought to be annotated with -> None. The reason for this is subtle. If __init__ assumed a return annotation of -> None, would that mean that an argument-less, un-annotated __init__ method should still be type-checked? Rather than leaving this ambiguous or introducing an exception to the exception, we simply say that __init__ ought to have a return annotation; the default behavior is thus the same as for other methods.)

使用 def __init__(self, n) -> None:def __init__(self, n): 之间的细微差别是什么?谁能用简单的话解释引用的摘录?

这仅在您关心类型注释时才重要,如果您不关心则可以跳过。它不会在运行时更改功能(除了在私有 __annotations__ 属性 中添加信息)。

那它有什么作用?
-> 用来记录一个函数returns.
的数据类型 然后是类型,在您的情况下,类型是 None.

所以它说该方法没有 return 任何东西,或者如果它有 return 东西它总是 None.

如果你想要return一些东西,你会把它改成return集的类型。

在python3.5出现了type annotation选项。 def __init__(self, n) -> None: 意味着 __init__ 应该总是 return None 类型,如果你不小心 return 一些不同于 None 的东西,它会很有帮助,特别是如果你使用 mypy 或其他类似的东西。但如果你更喜欢老方法,你可以忽略它。

它归结为 PEP 484 - The meaning of annotations 中的第一句话 任何类型检查器都应将任何没有注释的函数视为具有最通用的类​​型,或者忽略。 def __init__(self, n): 不会被检查,但 def __init__(self, n) -> None: 会。即使我们知道 __init__ 应该只 return None,检查器也不应该对它进行特殊处理。原因是你不知道作者有没有打算def __init__(self):勾选

主要是为了允许静态类型检查。默认情况下,mypy 将忽略未注释的函数和方法。

考虑以下定义:

class Foo:
    def __init__(self):
        return 3

f = Foo()

mypy,静态类型分析工具,默认看这个没什么问题:

$ mypy tmp.py
Success: no issues found in 1 source file

但是它产生了运行时TypeError(注意这里的python是Python3.8.6):

$ python tmp.py
Traceback (most recent call last):
  File "tmp.py", line 5, in <module>
    f = Foo()
TypeError: __init__() should return None, not 'int'

如果添加注释 -> None,则 mypy 将对方法进行类型检查并引发错误:

$ mypy tmp.py
tmp.py:3: error: No return value expected
Found 1 error in 1 file (checked 1 source file)
如果您试图通过声明 def __init__(self) -> int: 来规避检查,

mypy 甚至会抱怨:

$ mypy tmp.py
tmp.py:2: error: The return type of "__init__" must be None
Found 1 error in 1 file (checked 1 source file)

还值得注意的是,任何注释都会使mypy注意;如果您至少有一个带注释的参数,则缺少 return 类型与 -> None 相同:

def __init__(self, x: int):
     return x

将产生与显式 -> None 相同的“No return value expected”错误。不过,显式 return 类型通常比任何人为的参数类型提示更容易提供,并且可以说比尝试键入 self.

更清晰

对此事的批判性阅读是 MyPy issue 604 中包括 Guido 在内的帖子,他认为

I still think __init__ is a special case -- its return value is determined by how Python uses it, not by what the user might want it to return. I think the absence of -> None should never result in an error message here

结束于

gvanrossum added a commit that referenced this issue on Oct 1, 2018 [...] Make return type implicitly None for type checked __init__

长话短说,如果 linter 确定对于给定的 __init__ 可以进行静态类型检查(在您的情况下通过添加 n: int),它不会 - 也不应该 - 抱怨在没有 -> None 的情况下,将推断出