Este es otro caso de pylint
las reglas ciegas.
"Las clases no están destinadas a almacenar datos": esta es una declaración falsa. Los diccionarios no sirven para todo. Un miembro de datos de una clase es algo significativo, un elemento de diccionario es algo opcional. Prueba: puedes hacer dictionary.get('key', DEFAULT_VALUE)
para prevenir una KeyError
, pero no hay nada simple __getattr__
con defecto.
EDITAR - formas recomendadas de usar estructuras
Necesito actualizar mi respuesta. Ahora mismo, si necesita un struct
, tiene dos excelentes opciones:
a) Solo usa attrs
Esta es una biblioteca para eso:
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()
Lo que obtiene extra: no escribir constructores, valores predeterminados, validación, __repr__
objetos de solo lectura (para reemplazar namedtuples
, incluso en Python 2) y más.
b) Utilizar dataclasses
(Py 3.7+)
Siguiendo el comentario de hwjp, también recomiendo dataclasses
:
https://docs.python.org/3/library/dataclasses.html
Esto es casi tan bueno attrs
y es un mecanismo de biblioteca estándar ("baterías incluidas"), sin dependencias adicionales, excepto Python 3.7+.
Resto de respuesta anterior
NamedTuple
no es genial, especialmente antes de Python 3 typing.NamedTuple
:
https://docs.python.org/3/library/typing.html#typing.NamedTuple
- definitivamente deberías revisar el NamedTuple
patrón de "clase derivada de ". Python 2 - namedtuples
creado a partir de descripciones de cadenas - es feo, malo y "programar dentro de cadenas literales" estúpido.
Estoy de acuerdo con las dos respuestas actuales ("considere usar otra cosa, pero pylint no siempre es correcto" - la aceptada y "use pylint para suprimir el comentario"), pero tengo mi propia sugerencia.
Permítanme señalar esto una vez más: algunas clases están diseñadas solo para almacenar datos.
Ahora la opción a considerar también - use 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
Arriba tiene propiedades de solo lectura, que están bien para Objeto de valor (por ejemplo, como las del Diseño controlado por dominio), pero también puede proporcionar establecedores; de esta manera, su clase podrá asumir la responsabilidad de los campos que tiene, por ejemplo para hacer alguna validación, etc. (si tiene establecedores, puede asignarlos usándolos en el constructor, es decir, en self.foo = foo
lugar de directos self._foo = foo
, pero con cuidado, los establecedores pueden asumir que otros campos ya están inicializados, y luego necesita una validación personalizada en el constructor) .