Verwenden Sie das get / set-Muster (in Python)?


82

Die Verwendung von get / set scheint in Java (aus verschiedenen Gründen) eine gängige Praxis zu sein, aber ich sehe kaum Python-Code, der dies verwendet.

Warum verwenden oder vermeiden Sie get / set-Methoden in Python?


Erstellen Sie Antworten von allen. Zugegeben, diese Frage ist ein Ableger dieses einen stackoverflow.com/questions/1022970/… . Es scheint jedoch, dass ich von einer Horde von Leuten überfallen wurde, die sie aus einer "J" -Wortperspektive betrachteten. Nochmals vielen Dank für die Wiederherstellung meines Vertrauens in die geistige Gesundheit ...
Avery Payne

1
Der Kontext ist wichtig, und hier sind Python und Java einfach unterschiedlich. (Allerdings habe ich Python aus dem Titel entfernt, weil wir dafür Tags auf SO verwenden .;)

Antworten:


59

Cooler Link: Python ist nicht Java :)

In Java müssen Sie Getter und Setter verwenden, da Sie bei Verwendung öffentlicher Felder keine Möglichkeit haben, später Ihre Meinung zur Verwendung von Getter und Setter zu ändern. In Java können Sie also die Arbeit genauso gut aus dem Weg räumen. In Python ist dies albern, da Sie jederzeit mit einem normalen Attribut beginnen und Ihre Meinung ändern können, ohne die Clients der Klasse zu beeinträchtigen. Schreiben Sie also keine Getter und Setter.


3
Plus Setter / Getter erhöhen die Leistungskosten, insbesondere in Python.
Nick Dandoulakis

4
Dies stellt eine zusätzliche Belastung für den Klassen-Designer dar. In diesem Fall werden Variablen implizit Teil der öffentlichen API der Klasse. Denken Sie beim Layout einer Klasse explizit darüber nach, auf welche Instanzvariablen extern zugegriffen werden soll, und auf diejenigen, die eigentlich nur Teil Ihrer Klassenimplementierung sind. Stellen Sie den internen Implementierungen ein führendes '_' voran. Dies ist das Python-Warnzeichen dafür, dass sich diese Variable möglicherweise auch ändert oder sogar vollständig verschwindet, wenn sich die Implementierung ändert. Andernfalls tritt Implementierungswissen aus Ihrer Klasse aus, was eine spätere Änderung erschwert.
PaulMcG

8
@ Nick D: Ich denke nicht, dass Accessoren der richtige Ort sind, um Geschwindigkeitsoptimierungen in Python durchzuführen.
wRAR

1
@Nick D: Ich meine, das ist eine interpretierte Sprache, die die Lesbarkeit und nicht die Leistung fördert. Es gibt also viel bessere Orte für Optimierungen in einem Programm.
wRAR

2
@Paul: Es ist kein internes Attribut, es sei denn, es wird mit einem oder zwei führenden Unterstrichen benannt (wobei die erste Form im Allgemeinen bevorzugt wird, da letztere Pythons ungewöhnliche Namensverknüpfung ausführt). Wenn Sie keine Dokumente schreiben möchten und dieses Problem Sie stört, verwenden Sie einfach standardmäßig _name für alle Instanzattribute.

113

In Python können Sie einfach direkt auf das Attribut zugreifen, da es öffentlich ist:

class MyClass:

    def __init__(self):
        self.my_attribute = 0  

my_object = MyClass()
my_object.my_attribute = 1 # etc.

Wenn Sie beim Zugriff oder bei der Mutation des Attributs etwas unternehmen möchten, können Sie folgende Eigenschaften verwenden :

class MyClass:

    def __init__(self):
        self._my_attribute = 0

    @property
    def my_attribute(self):
        # Do something if you want
        return self._my_attribute

    @my_attribute.setter
    def my_attribute(self, value):
        # Do something if you want
        self._my_attribute = value

Entscheidend ist, dass der Client-Code gleich bleibt.


30

Hier ist, was Guido van Rossum dazu in Masterminds of Programming sagt

Was meinst du mit "Kampf gegen die Sprache"?

Guido: Das bedeutet normalerweise, dass sie versuchen, ihre Gewohnheiten fortzusetzen, die mit einer anderen Sprache gut funktionieren.

[...] Die Leute werden alles in eine Klasse verwandeln und jeden Zugriff in eine Zugriffsmethode verwandeln,
wo dies in Python wirklich keine kluge Sache ist. Sie haben mehr ausführlichen Code, der
schwieriger zu debuggen ist und viel langsamer läuft. Sie kennen den Ausdruck "Sie können FORTRAN in jeder Sprache schreiben?" Sie können Java auch in jeder Sprache schreiben.


14

Nein, es ist unpythonisch. Die allgemein akzeptierte Methode besteht darin, normale Datenattribute zu verwenden und diejenigen, die eine komplexere Get / Set-Logik benötigen, durch Eigenschaften zu ersetzen.


13
+1: "Wir sind alle Erwachsene hier". Der Code ist sichtbar. "private" und "getter / setter" erzeugen keinen Wert, wenn der gesamte Code sichtbar ist.
S.Lott

7

Die kurze Antwort auf Ihre Frage lautet Nein. Sie sollten bei Bedarf Eigenschaften verwenden. Ryan Tamyoko liefert die lange Antwort in seinem Artikel Getters / Setters / Fuxors

Der Grundwert, den Sie aus all dem herausnehmen sollten, ist, dass Sie sich bemühen möchten, sicherzustellen, dass jede einzelne Codezeile für den Programmierer einen Wert oder eine Bedeutung hat. Programmiersprachen sind für Menschen, nicht für Maschinen. Wenn Sie Code haben, der anscheinend nichts Nützliches tut, schwer zu lesen ist oder langweilig erscheint, stehen die Chancen gut, dass Python über eine Sprachfunktion verfügt, mit der Sie ihn entfernen können.


5

Ihre Beobachtung ist richtig. Dies ist kein normaler Stil der Python-Programmierung. Attribute sind alle öffentlich, sodass Sie einfach auf sie zugreifen (sie abrufen, festlegen, löschen), wie Sie es mit Attributen eines Objekts tun würden, das sie enthält (nicht nur Klassen oder Instanzen). Es ist leicht zu erkennen, wann Java-Programmierer Python lernen, da ihr Python-Code mit der Python-Syntax wie Java aussieht!

Ich stimme definitiv allen vorherigen Postern zu, insbesondere dem Link von @ Maximiliano zu Philipps berühmtem Artikel und dem Vorschlag von @ Max, dass alles Komplexere als die Standardmethode zum Festlegen (und Abrufen) von Klassen- und Instanzattributen darin besteht, Eigenschaften (oder Deskriptoren zu verwenden, um noch mehr zu verallgemeinern). um das Abrufen und Setzen von Attributen anzupassen! (Dazu gehört, dass Sie Ihre eigenen benutzerdefinierten Versionen von privaten, geschützten, befreundeten oder beliebigen Richtlinien hinzufügen können, wenn Sie etwas anderes als öffentlich wünschen.)

Als interessante Demo habe ich in Core Python Programming (Kapitel 13, Abschnitt 13.16) ein Beispiel für die Verwendung von Deskriptoren zum Speichern von Attributen auf der Festplatte anstatt im Speicher gefunden !! Ja, es ist eine seltsame Form von persistenten Speicher, aber es tut zeigen Ihnen ein Beispiel dessen , was möglich ist!

Hier ist ein weiterer verwandter Beitrag, den Sie möglicherweise ebenfalls nützlich finden: Python: Mehrere Eigenschaften, ein Setter / Getter


0

Ich war wegen dieser Antwort hierher gekommen (leider konnte ich nicht). Aber ich habe woanders eine Arbeit gefunden . Dieser folgende Code könnte eine Alternative zum Abrufen sein .
class get_var_lis: def __init__(self): pass def __call__(self): return [2,3,4] def __iter__(self): return iter([2,3,4]) some_other_var = get_var_lis
Dies ist nur eine Problemumgehung . Mit dem obigen Konzept könnten Sie auch in py leicht eine get / set-Methodik erstellen.


-10

Unser Lehrer zeigte ein Beispiel in der Klasse und erklärte, wann wir Accessor-Funktionen verwenden sollten.

class Woman(Human):
    def getAge(self):
        if self.age > 30:
            return super().getAge() - 10
        else:
            return super().getAge()

Ich habe Ihnen keine Abstimmungen gegeben, aber ich dachte, ich würde mich einschalten. Der Punkt der Diskussion ist "Warum brauchen wir get () / set (), um direkt in Python auf Eigenschaften zuzugreifen". In Java gibt es Sprachfunktionen, die dies wünschenswert machen. In Python nicht so sehr.
Avery Payne

7
Abgesehen davon, dass die Frage nicht wirklich beantwortet wird, ist das in dieser Antwort verwendete Beispiel beleidigend. Die Behauptung, dass Ihr Lehrer es benutzt hat, rechtfertigt seinen Sexismus nicht.
Touzen

Ich bezweifle, dass dies Sexismus zeigt, nur Ihre Naivität. In der Generation meiner Großmutter scherzten viele Frauen, dass ihr Alter einige Jahre jünger sei als es tatsächlich war. Außerdem hat es sowieso nichts mit der Antwort zu tun.
Johan Snowgoose
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.