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

新手上路,请多包涵

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

(注意 __init__ 的返回类型应该用 -> None -> None 。原因很微妙。如果 __init__ 假设返回注释 --- ,这是否意味着一个无参数、未注释的 __init__ 方法仍应进行类型检查?与其让这个模棱两可或引入异常,我们只是说 __init__ 应该有一个返回注释;因此默认行为与其他方法相同。)

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

原文由 user14612542 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

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

考虑以下定义:

 class Foo:
    def __init__(self):
        return 3

f = Foo()

mypy 静态类型分析工具,默认看不出有什么问题:

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

但它会产生一个运行时 TypeError (注意 python 这里是Python 3.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)

mypy 如果你试图通过声明 def __init__(self) -> int: 来规避检查,甚至会抱怨:

 $ 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 注意;缺少返回类型与 -> None 相同,如果您至少有一个带注释的参数:

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

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

原文由 chepner 发布,翻译遵循 CC BY-SA 4.0 许可协议

对此事的批判性阅读是 MyPy 问题 604 中包括 Guido 在内的线程,他认为

我仍然认为 __init__ 是一个特例——它的返回值取决于 Python 如何使用它,而不是用户可能希望它返回什么。我认为缺少 -> None 永远不会导致此处出现错误消息

总结于

gvanrossum 在 2018 年 10 月 1 日添加了引用此问题的提交 [ None __init__

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

原文由 Reinderien 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题