Was ist ein guter Weg, um Methoden in einer Python-Klasse zu bestellen?

86

Ich möchte Methoden in einer Python-Klasse bestellen, weiß aber nicht, welche Reihenfolge richtig ist.

Wenn ich Methoden in Eclipse mit PyDev extrahiere, setzt Eclipse die extrahierte Methode über die geänderte Methode. Dies setzt jedoch die Details der unteren Ebene vor die Details der höheren Ebene. Laut Onkel Bob sollte ich das Gegenteil tun, damit mein Code wie die Schlagzeilen einer Zeitung liest. Wenn ich Java programmiere, folge ich einfach seinem Rat.

Was ist die beste Vorgehensweise für Python?

Zetafisch
quelle
8
Es gibt keine bewährte Methode. Tun Sie, was am sinnvollsten ist - wichtige Dinge in der Nähe der Spitze sind eine gute Idee, und Konsistenz ist im Allgemeinen eine gute Sache. PEP-8 erwähnt dies nicht, und wenn es in Stein gemeißelt wäre, wäre es dort.
Gareth Latty
4
Und selbst PEP8 ist nicht immer in Stein gemeißelt.
Ignacio Vazquez-Abrams
1
Normalerweise mache ich das nach Gruppen in
Bezug
Es ist wichtig zu beachten, dass die Reihenfolge der Methodenfunktionen beliebig sein kann, da eine Klassendeklaration nur ihre Methodenfunktionen definiert und nicht aufruft . Auf diese Weise kann der Quellcode der Klassenmethodenroutinen erfolgreich Methodenfunktionen verwenden, die später in der Liste definiert werden.
DragonLord

Antworten:

64

Wie andere bereits betont haben, gibt es keinen richtigen Weg, um Ihre Methoden zu bestellen. Vielleicht wäre ein PEP-Vorschlag nützlich, aber trotzdem. Lassen Sie mich versuchen, Ihre Frage so objektiv wie möglich anzugehen.

  • Schnittstellen zuerst: Öffentliche Methoden und Python Magic-Funktionen definieren die Schnittstelle der Klasse. In den meisten Fällen möchten Sie und andere Entwickler eine Klasse verwenden, anstatt sie zu ändern. Daher werden sie an der Schnittstelle dieser Klasse interessiert sein. Wenn Sie es zuerst in den Quellcode einfügen, wird vermieden, dass Sie durch Implementierungsdetails scrollen, die Sie nicht interessieren.

  • Eigenschaften, magische Methoden , öffentliche Methoden: Es ist schwierig, die beste Reihenfolge zwischen diesen drei zu definieren, die alle Teil der Schnittstelle der Klasse sind. Wie @EthanFurman sagt, ist es am wichtigsten, für das gesamte Projekt bei einem System zu bleiben. Im Allgemeinen erwarten __init__()die Leute die beste erste Funktion in der Klasse, daher folge ich den anderen magischen Methoden direkt unten.

  • Lesereihenfolge: Grundsätzlich gibt es zwei Möglichkeiten, eine Geschichte zu erzählen: Bottom-up oder Top-down. Wenn Funktionen auf hoher Ebene an erster Stelle stehen, kann ein Entwickler durch Lesen der ersten Zeilen ein grobes Verständnis der Klasse erlangen. Andernfalls müsste man die gesamte Klasse lesen, um die Klasse zu verstehen, und die meisten Entwickler haben dafür keine Zeit. Als Faustregel sollten Sie Methoden über alle Methoden stellen, die von ihrem Körper aufgerufen werden.

  • Klassenmethoden und statische Methoden: Normalerweise wird dies durch die oben erläuterte Lesereihenfolge impliziert . Normale Methoden können alle Methoden mal aufrufen und stehen daher an erster Stelle. Klassenmethoden können nur Klassenmethoden und statische Methoden aufrufen und kommen als nächstes. Statische Methoden können keine anderen Methoden der Klasse aufrufen und stehen an letzter Stelle.

Hoffe das hilft. Die meisten dieser Regeln sind übrigens nicht Python-spezifisch. Mir ist keine Sprache bekannt, die die Reihenfolge der Methoden erzwingt, aber wenn ja, wäre dies sehr interessant und bitte kommentieren Sie.

Danijar
quelle
1
Normalerweise erzwingt eine Sprache keine Bestellung. Einige Sprachen haben jedoch gemeinsame Konventionen. Zum Beispiel hat C # StyleCop strenge Bestellregeln. Für Java siehe stackoverflow.com/questions/4668218 usw.
xmedeko
1
Klassenmethoden: Diese werden häufig als Konstruktoren verwendet und rufen dann normalerweise __init__explizit (in Kombination mit __new__) oder implizit (über den Standardkonstruktor) auf, sodass dies ein Grund wäre, sie zusammenzustellen __init__. (Obwohl ich noch nie gesehen habe sie gestellt vor __init__ .)
oulenz
13

Es gibt keine richtige Reihenfolge. Wählen Sie ein System und bleiben Sie dabei. Die, die ich benutze, ist:

class SomeClass(object):
    def __magic_methods__(self):
        "magic methods first, usually in alphabetical order"
    def _private_method(self):
        "worker methods next, also in alpha order"
    def a_method(self):
        "then normal methods, also in alpha order"
Ethan Furman
quelle
2
Was ist Ihre Präferenz für statische Methoden, Klassenvariablen und mit @property dekorierte Methoden?
John Mee
@ JohnMee: Klassenvariablen, die ich vor alles andere stelle; meine Faltverfahren Haut der @staticmethod, @classmethod, @propertyund alle andere @decoratorLinien , damit ich die Art der Methode verwenden , um festzustellen , wo es (mit der Ausnahme , dass Eigenschaften zwischen gehen neigen geht _private_methodsund normal_methods).
Ethan Furman
Wenn die Reihenfolge also im Grunde genommen von sehr privaten "magischen" Methoden zu privaten zu normalen Methoden wechselt, bedeutet das, dass @classmethods next ( @classmethod def a_class_method(cls)) dann @staticmethods ( @staticmethod def a_static_method()) kommt? Zumindest ist das die Richtlinie, wie ich sie verstehe ... (ohne dass meine IDE irgendetwas faltet, weil mir das nicht gefällt)
Kawu
2

Ich mache etwas Ähnliches wie @Ethan, das ich in Djangos Quelle gesehen habe, wo der Hauptunterschied große "############" Blockkommentare sind, um die Bereiche abzugrenzen. Zum Beispiel,

class SomeClass(object):
    #################
    # Magic Methods #
    #################
    def __magic_methods__(self):
        "magic methods first"

    ##################
    # Public Methods #
    ##################
    def a_method(self):
        "then normal methods, in order of importance"

    ###################
    # Private Methods #
    ###################
    def _private_method(self):
        "then worker methods, grouped by importance or related function"

Offensichtlich ist dies für kleinere Klassen weniger nützlich.

Matt Luongo
quelle
19
Aber ich kann sehen, dass sie magisch sind, öffentlich oder privat. Ich mag solche Kommentarblöcke selbst nicht; Ich kann mir den gefalteten Code ansehen, wenn ich eine Liste von allen sehen möchte. Einen Kommentar über einem bestimmten Block funktionsbezogener Methoden zu haben, würde ich tun, aber für diese Art von Kommentar - das sagen mir die Methodennamen.
Chris Morgan
Wieder mache ich das nur für größere Klassen. Ich finde es einfach, magische Methoden mit halbprivaten ( ) und namensverfälschten (_ ) Methoden zu verwechseln .
Matt Luongo
Ich war gerade dabei, die hässlichen ####Blöcke zu entfernen , als mir klar wurde, dass Sie sie absichtlich dort platzieren würden! Ich stimme jedoch der Reihenfolge zu , um die es in dieser Frage geht. Ich würde empfehlen, das ####aus diesem Beispiel zu entfernen, da es sich nicht auf den Umfang der Frage bezieht und Ihr Beispiel von einer kleinen Klasse ist, für die Sie ####sowieso nichts verwenden würden. :-)
Mateen Ulhaq
1
@MateenUlhaq Bitte beachten Sie die zweite und fünfte Richtlinie, die auf dem Bearbeitungsbildschirm angezeigt werden: "Klären Sie die Bedeutung, ohne sie zu ändern" und " Respektieren Sie immer den ursprünglichen Autor". (Beachten Sie, dass diese bedingungslos angewendet werden sollen, ohne Rücksicht auf die eigene Meinung des Herausgebers.) Der ganze und einzige Punkt dieser Antwort bestand darin, diese hässlichen Kommentarblöcke anzuzeigen. ohne sie sagt es genau das Gleiche wie Ethans Antwort und es hat keinen Sinn, hier zu sein. Sie haben sogar anerkannt, dass die Blöcke " absichtlich " vorhanden waren - wissend, warum sollten Sie sie entfernen?
Hallo
1
@MIWright Ich dachte, es würde den Rahmen der Frage sprengen. Wie Sie sehen können, enthält rev2 immer noch Material, das die Frage anders beantwortet als Ethans, mit einer anderen Reihenfolge (und Unterordnung!). Trotzdem zurückgerollt.
Mateen Ulhaq