Ich mache es wie:
def set_property(property,value):
def get_property(property):
oder
object.property = value
value = object.property
Ich bin neu in Python, daher erforsche ich immer noch die Syntax und möchte einige Ratschläge dazu.
python
getter-setter
Jorge Guberte
quelle
quelle
._x
(was keine Eigenschaft, sondern nur ein einfaches Attribut ist) umgehen dieproperty
Umhüllung. Nur Referenzen zum.x
Durchgehen derproperty
.Die "pythonische" Methode besteht nicht darin, "Getter" und "Setter" zu verwenden, sondern einfache Attribute zu verwenden, wie die Frage zeigt, und sie
del
zu löschen (aber die Namen werden geändert, um die unschuldigen ... Eingebauten zu schützen):Wenn Sie später die Einstellung ändern und abrufen möchten, können Sie dies tun, ohne den Benutzercode ändern zu müssen, indem Sie den
property
Dekorator verwenden:(Jede Dekorationsverwendung kopiert und aktualisiert das vorherige Eigenschaftsobjekt. Beachten Sie daher, dass Sie für jede Funktion / Methode zum Festlegen, Abrufen und Löschen denselben Namen verwenden sollten.
Nachdem Sie das oben Gesagte definiert haben, ist die ursprüngliche Einstellung, das Abrufen und Löschen von Code dieselbe:
Sie sollten dies vermeiden:
Erstens funktioniert das oben Gesagte nicht, da Sie kein Argument für die Instanz angeben, auf die die Eigenschaft (normalerweise
self
) gesetzt werden würde. Dies wäre:Zweitens dupliziert dies den Zweck von zwei speziellen Methoden,
__setattr__
und__getattr__
.Drittens haben wir auch die
setattr
undgetattr
eingebauten Funktionen.Der
@property
Dekorateur dient zum Erstellen von Gettern und Setzern.Beispielsweise könnten wir das Einstellungsverhalten ändern, um den festgelegten Wert einzuschränken:
Im Allgemeinen möchten wir die Verwendung vermeiden
property
und nur direkte Attribute verwenden.Dies wird von Benutzern von Python erwartet. Nach der Regel der geringsten Überraschung sollten Sie versuchen, Ihren Benutzern das zu geben, was sie erwarten, es sei denn, Sie haben einen sehr zwingenden Grund für das Gegenteil.
Demonstration
Angenommen, das geschützte Attribut unseres Objekts muss eine Ganzzahl zwischen 0 und einschließlich 100 sein und das Löschen verhindern, mit entsprechenden Meldungen, um den Benutzer über die ordnungsgemäße Verwendung zu informieren:
(Beachten Sie, dass
__init__
sichself.protected_value
die Eigenschaft auf die Eigenschaftsmethoden beziehtself._protected_value
. Auf diese Weise wird__init__
die Eigenschaft über die öffentliche API verwendet, um sicherzustellen, dass sie "geschützt" ist.)Und Verwendung:
Sind die Namen wichtig?
Ja, das tun sie .
.setter
und.deleter
machen Sie Kopien des ursprünglichen Eigentums. Auf diese Weise können Unterklassen das Verhalten ordnungsgemäß ändern, ohne das Verhalten im übergeordneten Element zu ändern.Damit dies funktioniert, müssen Sie die entsprechenden Namen verwenden:
Ich bin nicht sicher, wo dies nützlich wäre, aber der Anwendungsfall ist, wenn Sie eine Nur-Abrufen-, Festlegen- und / oder Löschen-Eigenschaft wünschen. Wahrscheinlich am besten bei semantisch derselben Eigenschaft mit demselben Namen bleiben.
Fazit
Beginnen Sie mit einfachen Attributen.
Wenn Sie später Funktionen zum Einstellen, Abrufen und Löschen benötigen, können Sie diese mit dem Eigenschaftendekorateur hinzufügen.
Vermeiden Sie Funktionen mit dem Namen
set_...
undget_...
- dafür sind Eigenschaften gedacht.quelle
__init__
bezieht sich die Methode auf,self.protected_value
aber der Getter und die Setter beziehen sich aufself._protected_value
. Könnten Sie bitte erklären, wie das funktioniert? Ich habe Ihren Code getestet und er funktioniert wie er ist - dies ist also kein Tippfehler.__init__
, oder?self.protected_value = start_protected_value
dass die Setter-Funktion tatsächlich aufgerufen wird. Ich dachte, es wäre eine Aufgabe.quelle
Mit
@property
und können@attribute.setter
Sie nicht nur die "pythonische" Methode verwenden, sondern auch die Gültigkeit von Attributen sowohl beim Erstellen des Objekts als auch beim Ändern überprüfen.Auf diese Weise "verbergen" Sie das
_name
Attribut tatsächlich vor Client-Entwicklern und führen auch Überprüfungen des Namenseigenschaftstyps durch. Beachten Sie, dass der Setter aufgerufen wird, wenn Sie diesen Ansatz auch während der Initiierung befolgen. Damit:Wird dazu führen:
Aber:
quelle
Schauen Sie sich den
@property
Dekorateur an .quelle
Sie können Accessoren / Mutatoren (dh
@attr.setter
und@property
) verwenden oder nicht, aber das Wichtigste ist , konsistent zu sein!Wenn Sie verwenden,
@property
um einfach auf ein Attribut zuzugreifen, zVerwenden Sie es, um auf jedes * Attribut zuzugreifen ! Es wäre eine schlechte Praxis, auf einige Attribute zuzugreifen
@property
und einige andere Eigenschaften ohne einen Accessor öffentlich zu lassen (dh Namen ohne Unterstrich), z. B. nichtBeachten Sie, dass
self.b
hier kein expliziter Accessor vorhanden ist, obwohl er öffentlich ist.Ähnlich ist es mit Setter (oder Mutatoren ), fühlen Sie sich frei zu verwenden ,
@attribute.setter
aber konsequent sein! Wenn Sie zEs fällt mir schwer, Ihre Absicht zu erraten. Einerseits sagen Sie, dass beide
a
undb
öffentlich sind (kein führender Unterstrich in ihren Namen), so dass ich theoretisch auf beide zugreifen / mutieren (get / set) dürfen sollte. Aber dann geben Sie einen expliziten Mutator nur für ana
, der mir sagt, dass ich vielleicht nicht in der Lage sein sollte, zu setzenb
. Da Sie einen expliziten Mutator angegeben haben, bin ich mir nicht sicher, ob das Fehlen von explizitem accessor (@property
) bedeutet, dass ich nicht auf eine dieser Variablen zugreifen kann oder dass Sie nur sparsam damit umgehen@property
.* Die Ausnahme ist, wenn Sie einige Variablen explizit zugänglich oder veränderbar machen möchten, aber nicht beide, oder wenn Sie beim Zugriff auf oder bei der Mutation eines Attributs eine zusätzliche Logik ausführen möchten. Dies ist, wenn ich persönlich benutze
@property
und@attribute.setter
(ansonsten keine expliziten Acessoren / Mutatoren für öffentliche Attribute).Zuletzt Vorschläge für PEP8 und Google Style Guide:
PEP8, Designing for Inheritance, sagt:
Auf der anderen Seite lautet die Empfehlung gemäß den Python-Sprachregeln / -eigenschaften des Google Style Guide :
Die Vorteile dieses Ansatzes:
und Nachteile:
quelle
@property
,@property
scheint es eine schlechte Entscheidung zu sein , den Rest auch zu verwenden .@property
(z. B. Ausführen einer speziellen Logik, bevor Sie ein Attribut zurückgeben). Warum würden Sie sonst ein Attribut mit@propery
und nicht mit anderen dekorieren ?@property
, oder? Wenn Ihr Getter istreturn this._x
und Ihr Setter istthis._x = new_x
, dann ist die Verwendung@property
überhaupt etwas albern.@property
die Konsistenz ist".Sie können die magischen Methoden
__getattribute__
und verwenden__setattr__
.Sei dir dessen bewusst
__getattr__
und__getattribute__
bin nicht dasselbe.__getattr__
wird nur aufgerufen, wenn das Attribut nicht gefunden wird.quelle