__init__的正确类型注释

101

Python中__init__函数的正确类型注释是什么?

class MyClass:
    ...

以下哪个更有意义?

def __init__(self):
    # type: (None) -> None

def __init__(self):
    # type: (MyClass) -> MyClass

def __init__(self):
    # type: (None) -> MyClass

通常情况下,我们会这样实例化类:myclass = MyClass(),但是__init__函数本身没有返回值。


出于我的好奇心,这是否必要/符合预期? - roganjosh
3
@roganjosh 不是的,这是一项受支持的功能。我发现它很有用,因为它可以帮助我的IDE(pycharm)检测类型不匹配。https://dev59.com/9lwY5IYBdhLWcg3wgH3y - hangc
但是您已将其标记为2.7,而2.7甚至不支持类型提示。我的问题更广泛,我不确定它对于__init __()是否有用。 - roganjosh
@roganjosh,你是对的,在这个例子中它没有用处。然而,我通常会将其扩展到其他需要输入变量的__init__函数中。我可以通过在2.7上安装typing和pycharm来使用一些功能。 - hangc
@roganjosh Python 2确实支持类型提示,请参见mypy文档。我认为应该尽可能地添加类型提示,特别是对于像__init__和可调用类之类的东西。 - Davos
2个回答

118

在注释中提到时应省略 self,并将 __init__() 标记为 -> None。这在PEP-0484中明确指定。


11
PEP 484指出,应将返回类型注释为 -> None,而不是省略self - user2357112
4
的确,规则并没有明确说明。但是这里提供了一些例子(链接在此),它们省略了 self - remram
2
这些示例展示了使用self作为方法签名和-> None作为返回类型的Python 3代码,这是您应该做的。如果您想要Python 2兼容性,可以将类型签名放入注释中,在这种情况下,您会在注释的类型签名中省略self。您肯定不会在方法参数中省略self,否则您将会得到参数计数不匹配错误,因为第一个参数将取代self。无论您如何标记它都没有关系,按照惯例它只是self。您可能是这个意思,但并不清楚。 - Davos
5
请问您说“应省略self”时,实际上是指不要省略self参数,而是要省略self的类型提示,是这个意思吗? - TheDiveO
2
顺便提一下,mypy 允许省略 __init__ 中的 -> None - 尽管这一点已经引起了广泛的讨论 - 因为 __init__ 只能有这种返回类型(对于类型检查,-> None 会自动添加),请参见 https://github.com/python/mypy/issues/604。 - F.Raab
显示剩余3条评论

7
如果您正在使用Python 3(我希望您是),自从mypy 0.641版本发布以来,根本不需要注释__init__方法,只要有至少一个已注释的参数,它必须始终为None,因为它不返回任何内容。在其他情况下,mypy将引发错误。这种行为困扰人们多年,但最终被修复了。
Guido在这里说:

New Feature: Allow Omitting Return Type for __init__ It is now possible to omit the return type of an annotated __init__ method without getting an error message. For example:

class Circuit:
    def __init__(self, voltage: float):
        self.voltage = voltage

In previous mypy versions this would elicit an error message:

error: The return type of "__init__" must be None

This error was just annoying as the only legal return declaration for __init__ is -> None, so we’ve removed it. Note that this only works if there’s at least one annotated argument! For __init__ methods without arguments you must still add -> None, otherwise the method will be treated as untyped, and its body will not be type checked at all. Examples:

class UntypedExample:
    # This method is not type-checked at all!
    def __init__(self):
        self.voltage = 0.0

class TypedExample:
    # This is how to ensure that a 0-argument __init__ is type-checked:
    def __init__(self) -> None:
        self.voltage = 0.0

相关讨论:

  1. 允许带有签名但没有返回类型的__init__
  2. __init__(self)缺少类型注释的函数

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接