Je suis tout à fait conscient que d' pylint
autres outils d'analyse statique ne savent pas tout et qu'il faut parfois désobéir à leurs conseils. (Ceci s'applique à différentes classes de messages, pas seulement à l' convention
art.)
Si j'ai des cours comme
class related_methods():
def a_method(self):
self.stack.function(self.my_var)
class more_methods():
def b_method(self):
self.otherfunc()
class implement_methods(related_methods, more_methods):
def __init__(self):
self.stack = some()
self.my_var = other()
def otherfunc(self):
self.a_method()
Évidemment, c'est artificiel. Voici un meilleur exemple, si vous aimez .
Je crois que ce style s'appelle "mixins".
Comme d’autres outils, attribue une note à pylint
ce code -21.67 / 10
, principalement parce qu’il pense more_methods
et related_methods
n’a pas d’ self
attributs otherfunc
, mais parce que sans exécuter le code, il ne peut apparemment pas voir et est mélangé à .stack
my_var
related_methods
more_methods
implement_methods
Les compilateurs et les outils d’analyse statique ne peuvent pas toujours résoudre le problème Halting , mais j’estime que c’est un cas dans lequel regarder ce qui en a été hérité implement_methods
montrerait que cela est parfaitement valide et que ce serait très facile à faire.
Pourquoi les outils d’analyse statique rejettent-ils ce modèle de POO valide (je pense)?
Non plus:
Ils ne sont même pas essayer de vérifier l' héritage ou
les mixins sont déconseillés en Python lisible et idiomatique
Le numéro 1 est évidemment incorrect, car si je demande pylint
à me parler d’une classe à moi qui hérite unittest.TestCase
qui utilise self.assertEqual
, (quelque chose défini uniquement dans unittest.TestCase
), elle ne se plaint pas .
Les mixins sont-ils non rythmiques ou découragés?
Réponses:
Les mixins ne sont tout simplement pas un cas d'utilisation pris en compte par l'outil. Cela ne veut pas dire que c'est forcément un mauvais cas d'utilisation, juste un cas rare pour python.
Que les mixins soient utilisés de manière appropriée dans un cas particulier est un autre problème. L'anti-pattern mixin que je vois le plus fréquemment consiste à utiliser mixins lorsqu'il n'y a jamais eu l'intention de mélanger une combinaison. C'est juste une façon détournée de cacher une classe de dieu. Si vous ne pouvez pas penser à une raison en ce moment d'échanger sur ou laisser de côté l' un des mixins, il ne devrait pas être un mixin.
la source
Je crois que les Mixins peuvent être, bien sûr, Pythonic. Cependant, le moyen le plus idiomatique de réduire au silence votre linter - et d’améliorer la lisibilité de vos Mixins - consiste à la fois (1) à définir des méthodes abstraites définissant explicitement les méthodes que les enfants d’un Mixin doivent mettre en œuvre et (2) à prédéfinir
None
champs évalués pour les membres de données Mixin que les enfants doivent initialiser.Appliquer ce modèle à votre exemple:
la source
abstract other(self): pass
chose échange la confusion du linter pour le mienJe pense que les mixins peuvent être bons, mais je pense aussi que pylint a raison dans ce cas. Clause de non-responsabilité: des éléments d'opinion suivent.
Une bonne classe, mixins compris, a une responsabilité claire. Idéalement, un mixin devrait contenir tout l'état auquel il va accéder et la logique pour le gérer. Par exemple, un bon mélange peut ajouter un
last_updated
champ à une classe de modèle ORM, fournir une logique pour le définir et des méthodes pour rechercher l'enregistrement le plus ancien / le plus récent.Faire référence à des membres d'instance non déclarés (variables et méthodes) semble un peu bizarre.
La bonne approche dépend beaucoup de la tâche à accomplir.
Il peut s'agir d'un mélange avec le bit d'état retenu.
Il peut s'agir d'une hiérarchie de classes différente dans laquelle les méthodes que vous distribuez actuellement via un mixin appartiennent à une classe de base, tandis que les différences d'implémentation de niveau inférieur appartiennent à des sous-classes. Cela semble plus adapté à votre cas avec les opérations de la pile.
Ce peut être un décorateur de classe qui ajoute une méthode ou deux; Cela a généralement du sens lorsque vous devez transmettre des arguments au décorateur pour affecter la génération de la méthode.
Énoncez votre problème, expliquez vos préoccupations plus grandes en matière de conception, nous pourrons alors nous disputer si quelque chose est contraire à votre modèle.
la source
Le linter ignore que vous utilisez une classe en tant que mixin. Pylint sait que vous utilisez un mixin si vous ajoutez le suffixe 'mixin' ou 'Mixin' à la fin du nom de la classe, puis linter cesse de se plaindre.
Les mixins ne sont ni mauvais ni bons en soi, ce n'est qu'un outil. Vous leur faites un bon ou mauvais usage.
la source
Les mixins sont-ils ok?
Les mixins ne sont pas découragés - ils constituent un bon cas d'utilisation pour l'héritage multiple.
Pourquoi votre linter se plaint-il?
Pylint se plaint évidemment parce qu'elle ne sait pas où
otherfunc
,stack
etmy_var
vient.Banal?
Il n'y a aucune raison immédiatement apparente de séparer ces deux méthodes en classes parentes distinctes, que ce soit dans votre exemple dans la question ou dans votre exemple lié plus trivial, présenté ici.
Frais de mixins et de bruit
Le coût de ce que vous faites fait en sorte que votre rapport de bruit soit bruyant. Ce bruit peut masquer des problèmes plus importants avec votre code. C'est un coût important à peser. Un autre coût est que vous séparez votre code interconnecté en différents espaces de noms, ce qui peut compliquer la tâche des programmeurs.
Conclusion
L'héritage permet la réutilisation du code. Si vous obtenez une réutilisation du code avec vos mixins, très bien, ils ont créé pour vous une valeur qui dépasse probablement les autres coûts possibles. Si vous n'obtenez pas la réutilisation / la déduplication de lignes de code, vous n'obtenez probablement pas beaucoup de valeur pour vos mixins, et à ce stade, je pense que le coût du bruit est supérieur aux avantages.
la source