Це ще один випадок pylint
сліпих правил.
"Класи не призначені для зберігання даних" - це помилкове твердження. Словники корисні не для всього. Член даних класу - щось значуще, елемент словника - щось необов’язкове. Доказ: ви можете зробити, dictionary.get('key', DEFAULT_VALUE)
щоб запобігти KeyError
, але немає простого__getattr__
за замовчуванням.
EDIT - рекомендовані способи використання конструкцій
Мені потрібно оновити свою відповідь. Прямо зараз - якщо вам потрібноstruct
, у вас є два чудових варіанти:
а) Просто використовуйте attrs
Це бібліотека для цього:
https://www.attrs.org/en/stable/
import attr
@attr.s
class MyClass(object): # or just MyClass: for Python 3
foo = attr.ib()
bar = attr.ib()
Що ви отримуєте додатково: не написання конструкторів, значень за замовчуванням, валідація, __repr__
об'єкти лише для читання (для заміни namedtuples
навіть у Python 2) та багато іншого.
б) Використовувати dataclasses
(Py 3.7+)
Після коментаря hwjp я також рекомендую dataclasses
:
https://docs.python.org/3/library/dataclasses.html
Це майже так само добре attrs
, і є стандартним механізмом бібліотеки ("батареї включені"), без додаткових залежностей, крім Python 3.7+.
Решта попередньої відповіді
NamedTuple
не чудово - особливо перед python 3's typing.NamedTuple
:
https://docs.python.org/3/library/typing.html#typing.NamedTuple
- вам обов'язково слід перевірити NamedTuple
шаблон "класу, похідного від ". Пітон 2 -namedtuples
створений з опису рядків - некрасивий, поганий і "програмування всередині літеральних рядків" дурний.
Я погоджуюся з двома поточними відповідями ("розглянути можливість використання чогось іншого, але pylint не завжди є правильним" - прийнятим, і "використовувати коментар, що пригнічує пілінт"), але у мене є своя пропозиція.
Дозвольте це ще раз зазначити: деякі класи призначені просто для зберігання даних.
Тепер варіант також розглянути - використання property
-ies.
class MyClass(object):
def __init__(self, foo, bar):
self._foo = foo
self._bar = bar
@property
def foo(self):
return self._foo
@property
def bar(self):
return self._bar
Вище маєте властивості лише для читання, що є нормальним для об'єкта цінності (наприклад, таких, як у дизайні, керованому доменом), але ви також можете надати сетерів - таким чином ваш клас зможе взяти на себе відповідальність за поля, які у вас є - наприклад зробити деяку перевірку і т. д. (якщо у вас є сеттери, ви можете призначити їх використання в конструкторі, тобто self.foo = foo
замість прямого self._foo = foo
, але обережного, вони можуть передбачити ініціалізацію інших полів, і тоді вам потрібна спеціальна перевірка в конструкторі) .