J'exécute pylint sur du code et je reçois le message d'erreur "Trop peu de méthodes publiques (0/2)". Que signifie ce message? Les pylint docs ne sont pas utiles:
Utilisé lorsque la classe a trop peu de méthodes publiques, assurez-vous que cela en vaut vraiment la peine.
En gros, l’erreur indique que les classes ne sont pas destinées à seulement stocker des données, car vous les traitez comme un dictionnaire. Les classes doivent avoir au moins quelques méthodes pour exploiter les données qu'elles détiennent.
Si votre classe ressemble à ceci:
class MyClass(object):
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
Pensez à utiliser un dictionnaire ou un namedtuple
à la place. Bien que si une classe semble être le meilleur choix, utilisez-le. Pylint ne sait pas toujours ce qu'il y a de mieux.
Notez que namedtuple
est immuable et que les valeurs attribuées lors de l'instanciation ne peuvent pas être modifiées ultérieurement.
Si vous étendez une classe, ma suggestion est de désactiver systématiquement cet avertissement et de passer, par exemple, dans le cas des tâches de céleri:
class MyTask(celery.Task): # pylint: disable=too-few-public-methods
"""base for My Celery tasks with common behaviors; extends celery.Task
...
Même si vous ne développez qu'une seule fonction, vous avez certainement besoin d'une classe pour que cette technique fonctionne, et cette extension est définitivement meilleure que le piratage des classes tierces!
Ceci est un autre cas de règles aveugles de pylint
.
"Les classes ne sont pas destinées à stocker des données" - ceci est une fausse déclaration. Les dictionnaires ne sont pas bons pour tout. Un membre de données d'une classe est significatif, un élément de dictionnaire est optionnel. Preuve: vous pouvez faire dictionary.get('key', DEFAULT_VALUE)
pour empêcher un KeyError
, mais il n’existe pas de simple __getattr__
avec défaut.
J'ai besoin de mettre à jour ma réponse. Pour le moment, si vous avez besoin de struct
, vous avez deux options intéressantes:
attrs
Voici une bibliothèque pour cela:
https://www.attrs.org/fr/stable/
import attr
@attr.s
class MyClass(object): # or just MyClass: for Python 3
foo = attr.ib()
bar = attr.ib()
Ce que vous obtenez en plus: ne pas écrire de constructeurs, valeurs par défaut, validation, __repr__
, objets en lecture seule (pour remplacer namedtuples
, même dans Python 2) et plus.
dataclasses
(Py 3.7+)Après le commentaire de hwjp, je recommande également dataclasses
:
https://docs.python.org/3/library/dataclasses.html
C'est presque aussi bon que attrs
et c'est un mécanisme de bibliothèque standard ("piles incluses"), sans dépendance supplémentaire, sauf Python 3.7+.
NamedTuple
n'est pas terrible - surtout avant python 3's typing.NamedTuple
: https://docs.python.org/3/library/typing.html#typing.NamedTuple - vous devriez absolument vérifier le motif "class dérivé de NamedTuple
" . Python 2 - namedtuples
créé à partir de descriptions de chaînes - est laid, mauvais et "programmer à l'intérieur de littéraux de chaîne" stupide.
Je suis d’accord avec les deux réponses actuelles ("envisagez d’utiliser quelque chose d’autre, mais pylint n’est pas toujours correct" - celle acceptée et "utilisez un commentaire de suppression de pylint"), mais j’ai ma propre suggestion.
Permettez-moi de le rappeler une fois de plus: Certaines classes ont pour but de stocker des données .
Maintenant, l'option permettant également d'envisager - utilise 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
Ci-dessus, vous avez les propriétés en lecture seule, ce qui est OK pour Value Object (par exemple, celles de Domain Driven Design), mais vous pouvez également fournir des setters - de cette façon, votre classe pourra assumer la responsabilité des champs que vous avez - par exemple faire une validation, etc. (si vous avez des setters, vous pouvez les affecter en utilisant le constructeur, ie self.foo = foo
au lieu de direct self._foo = foo
, mais attention, les installateurs peuvent supposer que d’autres champs ont déjà été initialisés et vous devez ensuite procéder à une validation personnalisée dans le constructeur).
J'ai ajouté une méthode supplémentaire à ma classe
def __str__(self):
return self.__class__.__name__
problème résolu