Python 在 __init__ 之外定义的实例属性 attribute_name

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19284857/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:20:07  来源:igfitidea点击:

Instance attribute attribute_name defined outside __init__

pythonconstructorpylint

提问by Steven Liao

I split up my class constructor by letting it call multiple functions, like this:

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

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

While my interpreter happily runs my code, Pylint has a complaint:

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

Instance attribute attribute_name defined outside __init__

Instance attribute attribute_name defined outside __init__

A cursory Google search is currently fruitless. Keeping all constructor logic in __init__seems unorganized, and turning off the Pylint warning also seems hack-ish.

粗略的谷歌搜索目前没有结果。保留所有构造函数逻辑__init__似乎是无组织的,关闭 Pylint 警告也似乎是 hack-ish。

What is a/the Pythonicway to resolve this problem?

解决此问题的/ Pythonic方法是什么?

回答by roippi

Just return a tuple from parse_arguments()and unpack into attributes inside __init__as needed.

只需根据需要从parse_arguments()内部返回一个元组并解压缩到属性中__init__

Also, I would recommend that you use Exceptions in lieu of using exit(1). You get tracebacks, your code is reusable, etc.

另外,我建议您使用 Exceptions 代替使用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]

回答by sthenault

The idea behind this message is for the sake of readability. We expect to find all the attributes an instance may have by reading its __init__method.

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

You may still want to split initialization into other methods though. In such case, you can simply assign attributes to None(with a bit of documentation) in the __init__then call the sub-initialization methods.

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

回答by Ben

For each attribute you want to set via function, call the function from the init. For example, the following works for me to set the attribute ascii_txt...

对于要通过函数设置的每个属性,从 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

回答by Ofer Elboher

Although the definition of instance variables outside initisn't recommended in general, there are rare cases in which it is natural. For example, when you have a parent class that defines several variables that its child classes won't use, and whose definition will make its child waste time or resources, or will be simply unaesthetic.

虽然一般不推荐在init之外定义实例变量,但在极少数情况下它是自然的。例如,当你有一个父类定义了几个它的子类不会使用的变量,而它的定义会让它的子类浪费时间或资源,或者只是不美观。

One possible solution to this is using an init-extention function, that each child class may override, and in this function use function setattr in order to define the class-unique instance variables. May be this is not too aesthetic as well, but it eliminates the here-discussed linting warning.

一种可能的解决方案是使用 init-extention 函数,每个子类都可以覆盖该函数,并且在该函数中使用函数 setattr 来定义类唯一的实例变量。可能这也不太美观,但它消除了此处讨论的 linting 警告。

回答by lowzhao

If you are using Python 3, you can try

如果您使用的是 Python 3,则可以尝试

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

Although not as pythonic as the accepted answer, but it should get away the Pylint alert.

虽然不像接受的答案那么 pythonic,但它应该摆脱 Pylint 警报。

And if you don't concern about type and don't want to create a new object with object()use:

如果您不关心类型并且不想object()使用 use创建新对象:

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

As Nonewill cause type not match error.

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