web-dev-qa-db-fra.com

Que signifie le message "Trop peu de méthodes publiques" de pylint

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.

87
monsur

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.

101
Blender

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!

37
sage

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.

EDIT - manières recommandées d'utiliser des structures

J'ai besoin de mettre à jour ma réponse. Pour le moment, si vous avez besoin de struct, vous avez deux options intéressantes:

a) Il suffit d'utiliser 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.

b) Utilisez 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+.

Reste de la réponse précédente

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

7
Tomasz Gandor

J'ai ajouté une méthode supplémentaire à ma classe

def __str__(self):
    return self.__class__.__name__

problème résolu

1
Sean Bradley