Instance attribute attribute_name defined outside

2019-01-07 07:58发布

问题:

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:

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.

What is a/the Pythonic way to resolve this problem?

回答1:

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.

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.



回答2:

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

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

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]


回答3:

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...

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