Mir ist völlig bewusst, dass pylint
und andere statische Analysewerkzeuge nicht allwissend sind, und manchmal müssen ihre Ratschläge missachtet werden. (Dies gilt für verschiedene Nachrichtenklassen, nicht nur für convention
s.)
Wenn ich Unterricht haben möchte
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()
Offensichtlich ist das erfunden. Hier ist ein besseres Beispiel, wenn Sie möchten .
Ich glaube, dieser Stil wird "Mixins" genannt.
Wie bei anderen Tools wird pylint
dieser Code mit bewertet -21.67 / 10
, vor allem, weil er denkt more_methods
und related_methods
keine self
oder Attribute otherfunc
hat stack
, und my_var
weil er ohne Ausführung des Codes anscheinend nicht sehen kann related_methods
und darin more_methods
gemischt ist implement_methods
.
Compiler und statische Analysewerkzeuge können das Problem des Anhaltens nicht immer lösen , aber ich bin der Meinung, dass ein Blick auf das, was von geerbt implement_methods
wird, durchaus berechtigt ist, und das wäre sehr einfach.
Warum lehnen statische Analysetools dieses gültige (meiner Meinung nach) OOP-Muster ab?
Entweder:
Sie versuchen nicht einmal , die Vererbung zu überprüfen oder
Mixins werden in idiomatischem, lesbarem Python nicht empfohlen
Nr. 1 ist offensichtlich falsch, da ich pylint
mich nicht beschwere, wenn ich nach einer Klasse von mir frage , die unittest.TestCase
verwendet self.assertEqual
(etwas, das nur in definiert ist unittest.TestCase
) .
Sind Mixins unpythonisch oder entmutigt?
Antworten:
Mixins sind einfach kein Anwendungsfall, der vom Tool berücksichtigt wurde. Das bedeutet nicht, dass es notwendigerweise ein schlechter Anwendungsfall ist, nur ein ungewöhnlicher für Python.
Ob Mixins im Einzelfall angemessen eingesetzt werden, ist eine andere Frage. Das Anti-Pattern, das ich am häufigsten sehe, verwendet Mixins, wenn immer nur eine Kombination gemischt werden soll. Das ist nur ein Umweg, um eine Gottesklasse zu verstecken. Wenn Sie nicht aus einem Grunde denken können , gerade jetzt zu tauschen oder auslassen eine der Mixins, sollte es kein mixin sein.
quelle
Ich glaube, dass Mixins absolut pythonisch sein können. Die idiomatische Methode, um Ihren Linter zum Schweigen zu bringen und die Lesbarkeit Ihrer Mixins zu verbessern, besteht darin, (1) abstrakte Methoden zu definieren, die explizit die Methoden definieren, die die untergeordneten Elemente eines Mixins implementieren müssen, und (2) vordefinieren
None
-bewertete Felder für Mixin-Datenelemente, die Kinder initialisieren müssen.Anwenden dieses Musters auf Ihr Beispiel:
quelle
abstract other(self): pass
Sache die Verwirrung des linter für meine tauschtIch denke, Mixins können gut sein, aber ich denke auch, dass Pylint in diesem Fall richtig ist. Haftungsausschluss: Es folgt meinungsbasiertes Material.
Eine gute Klasse, Mixins eingeschlossen, hat eine klare Verantwortung. Idealerweise sollte ein Mixin den gesamten Status enthalten, auf den es zugreifen wird, sowie die Logik, mit der es umgeht.
last_updated
Zum Beispiel könnte ein gutes Mixin ein Feld zu einer ORM-Modellklasse hinzufügen , eine Logik zum Festlegen und Methoden zum Suchen nach dem ältesten / neuesten Datensatz bereitstellen.Auf nicht deklarierte Instanzmitglieder (Variablen und Methoden) zu verweisen, sieht etwas seltsam aus.
Der richtige Ansatz hängt stark von der jeweiligen Aufgabe ab.
Es kann sich um eine Mischung mit dem relevanten Status handeln, der darin gespeichert ist.
Es kann sich um eine andere Klassenhierarchie handeln, bei der sich die Methoden, die Sie derzeit über ein Mixin verteilen, in einer Basisklasse befinden, während Implementierungsunterschiede auf niedrigerer Ebene zu Unterklassen gehören. Dies scheint für Ihren Fall mit den Stapeloperationen am besten geeignet zu sein.
Es kann ein Klassendekorateur sein, der eine oder zwei Methoden hinzufügt. Dies ist normalerweise sinnvoll, wenn Sie einige Argumente an den Decorator übergeben müssen, um die Methodengenerierung zu beeinflussen.
Geben Sie Ihr Problem an, erklären Sie Ihre größeren Designprobleme, und wir könnten uns darüber streiten, ob etwas in Ihrem Fall ein Anti-Pattern ist.
quelle
Dem Linter ist nicht bekannt, dass Sie eine Klasse als Mixin verwenden. Pylint ist bewusst, dass Sie ein Mixin verwenden, wenn Sie das Suffix 'mixin' oder 'Mixin' am Ende des Klassennamens hinzufügen, dann hört der Linter auf, sich zu beschweren.
Mixins sind an sich nicht schlecht oder gut, sie sind nur ein Werkzeug. Sie machen sie eine gute oder eine schlechte Verwendung.
quelle
Sind Mixins in Ordnung?
Mixins werden nicht entmutigt - sie sind ein guter Anwendungsfall für die Mehrfachvererbung.
Warum beschwert sich dein Linter?
Pylint beschwert sich offenbar , weil es nicht , wo das nicht kennt
otherfunc
,stack
undmy_var
herkommt.Trivial?
Es gibt keinen offensichtlichen Grund, diese beiden Methoden in separate übergeordnete Klassen zu unterteilen, weder in Ihrem Beispiel in der Frage noch in Ihrem hier gezeigten trivialeren verknüpften Beispiel.
Kosten für Mixins und Lärm
Die Kosten für das, was Sie tun, verursachen Lärm in Ihrem Linter-Bericht. Dieses Rauschen kann wichtigere Probleme mit Ihrem Code verdecken. Dies ist ein wichtiger Kostenfaktor. Ein weiterer Nachteil ist, dass Sie Ihren zusammengehörigen Code in verschiedene Namespaces aufteilen, wodurch es für Programmierer möglicherweise schwieriger wird, die Bedeutung von zu erkennen.
Fazit
Die Vererbung ermöglicht die Wiederverwendung von Code. Wenn Sie Code mit Ihren Mixins wiederverwenden, haben sie einen Mehrwert für Sie geschaffen, der wahrscheinlich die möglichen anderen Kosten überwiegt. Wenn Sie keine Wiederverwendung / Deduplizierung von Codezeilen erhalten, erhalten Sie wahrscheinlich nicht viel Wert für Ihre Mixins, und zu diesem Zeitpunkt sind die Kosten für das Rauschen meiner Meinung nach höher als die Vorteile.
quelle