Python 在里面输入注释 __init__

Python Typing Annotation inside __init__

如何注解在__init__之后才可用的实例变量的类型?我想按照 POLS.

列出 __init__ 内的所有实例属性

MWE:

class MyClass(object):
   def __init__(self):
      self.foo :Union[CustomClass, None] = None

   def set_foo(self):
      self.foo = CustomClass()

   def use_foo(self):
      self.foo.do_something()

__init__里面,如果我只是把foo注释成self.foo: CustomClass = None,Pylint会报错:

T484: Incompatible types in assignment (expression has type None, variable has type "CustomClass").

但是,如果我将 foo 注释为 self.foo: Union[CustomClass, None] = None(如上面的 MWE),PyLint 将在 use_foo 函数内部抱怨:

T484: "None" has no attribute "do_something".

如何让 PyLint 开心? (w/o 禁用 T484)

我能想到的最简单的方法是简单地将 self.foo 初始化为 "" 而不是 None.

这意味着 self.foo.upper() 将可用,因此 pylint 将没有理由抱怨。

如果您不希望 use_foo 在调用 get_foo(可能称为 set_foo)之前可用,您可以检查以确保 self.foo 被填充,或者保留一个布尔字段说明它是否曾经 运行.


如果您的 class 比字符串复杂一点,您必须在使用 self.foo 之前快速检查一下。

def use_foo(self):
    if self.foo is None:
        raise EnvironmentError("You haven't called get_foo!")
    self.foo.upper()

这不是一个非常干净的解决方案 - 我认为我们可以做得更好。

让我们尝试将此检查外包给装饰者;

def ensure_foo(func):
    def inner_func(self, *args, **kwargs):
        if self.foo is None:
            raise EnvironmentError("You haven't called get_foo!")
        func(self, *args, **kwargs)
    return inner_func

我还没有亲自用 pylint 尝试过这个 - 但如果 pylint 足够聪明,可以弄清楚发生了什么,那么在你的 class 方法之上拍打 @ensure_foo 将会很多比到处放 None 检查更清洁...