Pythonic: использование __dict__ в функции self.__ init__ класса

При кодировании нового класса с помощью spyder IDE и использовании pylint для проверки конечного результата я столкнулся с сообщениями об ошибках (но код работает как ожидалось без ошибок).

Контекст: в функции конструктора, я хочу создать новых членов (довольно много). Обычно их достаточно мало, поэтому я использую это кодирование:

class MyClass():
    def __init__(self):
        self.a = ...
        self.b = ...

Но в случае многих членов (скажем, 10), со всеми установленными одинаковыми начальными значениями (скажем, все они dict()), у меня возникло соблазн сделать это:

class MyClass():
    def __init__(self):
        _vars = ["a", "b", "c", ...]
        for _var in _vars:
            self.__dict__[_var] = dict()

Далее в классе я ссылался на элемент, используя:

class MyClass():
    def my_method(self):
        print self.c

Ошибка с pylint (в spyder):

При использовании pylint в этом файле у меня появляется сообщение об ошибке:

MyClass.my_method: экземпляр "MyClass" не имеет "c'member".

Однако код работает просто отлично, без ошибок, т.е. Я могу получить доступ к члену "c" без каких-либо проблем.

Вопрос: это правильное кодирование, или я должен избегать такого метода для инициализации членов?

Ответ 1

Да, разумно сразу обновлять словарь экземпляра. Кроме того, вы можете использовать setattr для обновления переменных. Я видел оба подхода, используемые в производственном коде.

С setattr нет необходимости напрямую касаться словаря экземпляра:

class MyClass():
    def __init__(self):
        for var in 'a', 'b', 'c':
            setattr(self, var, dict())

Но если вы сразу обновите словарь экземпляра, есть несколько возможных улучшений. Например, использование vars() вместо __dict__ немного приятнее. Кроме того, вы можете использовать метод dict.update с аргументами ключевого слова:

class MyClass():
    def __init__(self):
        vars(self).update(a=dict(), b=dict(), c=dict())

Ответ 2

Это действительно хорошо, но я обычно рекомендую избегать беспорядка с __dict__ напрямую. Что, если, например, вы хотите поместить пользовательский сеттер для атрибута вашего объекта позже по дороге?

В примере вашего примера вы можете просто заменить строку в цикле for следующим образом:

setattr(self, _var, dict())