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())