我通过让类构造函数调用多个函数来拆分类构造函数,如下所示:

class Wizard:
    def __init__(self, argv):
        self.parse_arguments(argv)
        self.wave_wand() # declaration omitted

    def parse_arguments(self, argv):
        if self.has_correct_argument_count(argv):
            self.name = argv[0]
            self.magic_ability = argv[1]
        else:
            raise InvalidArgumentsException() # declaration omitted

# ... irrelevant functions omitted

当我的解释器愉快地运行我的代码时,Pylint有一个抱怨:

实例属性attribute_name定义在__init__之外

粗略的谷歌搜索目前没有结果。将所有构造函数逻辑保存在__init__中似乎是杂乱无章的,而且关闭Pylint警告也显得很笨拙。

python解决这个问题的方法是什么?


当前回答

这条消息背后的想法是为了可读性。我们希望通过读取实例的__init__方法来找到实例可能具有的所有属性。

不过,您可能仍然希望将初始化拆分为其他方法。在这种情况下,你可以在__init__中简单地将属性赋值给None(带一些文档),然后调用子初始化方法。

其他回答

只需从parse_arguments()返回一个元组,并根据需要将其解压缩到__init__中的属性中。

另外,我建议你使用exception代替exit(1)。你得到了回溯,你的代码是可重用的,等等。

class Wizard:
    def __init__(self, argv):
        self.name,self.magic_ability = self.parse_arguments(argv)

    def parse_arguments(self, argv):
        assert len(argv) == 2
        return argv[0],argv[1]

尽管通常不建议在init之外定义实例变量,但在极少数情况下,这样做是很自然的。例如,当你有一个父类,它定义了几个它的子类不会使用的变量,而这些变量的定义会让它的子类浪费时间或资源,或者仅仅是不美观。

一种可能的解决方案是使用初始化扩展函数,每个子类都可以覆盖该函数,并在该函数中使用函数setattr来定义类唯一的实例变量。也许这也不太美观,但它消除了这里讨论的绒线警告。

这条消息背后的想法是为了可读性。我们希望通过读取实例的__init__方法来找到实例可能具有的所有属性。

不过,您可能仍然希望将初始化拆分为其他方法。在这种情况下,你可以在__init__中简单地将属性赋值给None(带一些文档),然后调用子初始化方法。

如果你正在使用python3,你可以试试

class Wizard:
    def __init__(self, argv):
        self.name: str = str()
        self.magic_ability: str = str()
        self.parse_arguments(argv)
        self.wave_wand() # declaration omitted

    def parse_arguments(self, argv):
        if self.has_correct_argument_count(argv):
            self.name = argv[0]
            self.magic_ability = argv[1]
        else:
            raise InvalidArgumentsException() # declaration omitted

# ... irrelevant functions omitted

虽然不像公认的答案那样python化,但它应该可以摆脱Pylint警告。

如果你不关心类型,也不想用object()创建一个新对象,请使用:

class Wizard:
    def __init__(self, argv):
        self.name = type(None)()
        # ...

因为None将导致类型不匹配错误。

对于想要通过function设置的每个属性,从init调用该函数。例如,下面的工作为我设置属性ascii_txt…

def __init__(self, raw_file=None, fingerprint=None):
    self.raw_file = raw_file
    self.ascii_txt = self.convert_resume_to_ascii()

def convert_resume_to_ascii(self):
    ret_val = self.raw_file.upper()
    return ret_val