Getter und Setter

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
tom1968
User
Beiträge: 38
Registriert: Sonntag 30. Juni 2013, 09:54

Eine Frage zu Getter und Setter unter Python, die man offenbar eher nicht verwenden soll.

Bezieht sich das nur auf 'triviale' Getter (und Setter) wie z.B.

Code: Alles auswählen

class Beispiel():
....
    def get_wert(self):
        return self.wert
....
Also Getter-Methoden die nichts machen außer den gewünschten Wert zurückzugeben, oder auch auf Methoden die zwar Werte zurückgeben diese aber vorher berechnen etc. z.B. so:

Code: Alles auswählen

class Beispiel():
....
    def get_wert(self):
        self.wert = self.andererwert +10 # vereinfachtes Beispiel
        return self.wert
....
Was mich auch interessieren würde: Was spricht gegen ein Verwendung wie im ersten Beispiel ?
So eine genormte und ausschließliche Schnittstelle scheint, zumindest auf den ersten Blick, doch eine tolle Sache zu sein
- leichter lesbar und leichter wartbar (z.B. für den Fall dass später mal ein Fall eintritt wo der Wert (erstes Beispiel) generell modifiziert zurückgegeben werden soll ?
Auch dürften ungewünschte Nebeneffekte eher weniger auftreten wenn die Schnittstellen klar deklariert sind ?

Thomas
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@tom1968: Ist die Schnittstelle denn bei einfachen Attributzugriffen (also auf das "blanke" `.wert` im Beispiel) unklar? Man kann doch dokumentieren, dass ein Objekt in `.wert` den zugewiesenen Parameter gespeichert hat. Oder geht es dir um read-only-Zugriffe, bei denen der Benutzer nicht nachträglich noch etwas verändern soll?
BlackJack

@tom1968: Gegen simple Getter/Setter spricht, das sie unnötigen Code darstellen. Und wenn man das später mal ändern möchte, dann gibt es in Python Properties (`property()`) , also berechnete Attribute die beim Zugriff Code ausführen. Man hat also eine klare API, die sich auch nicht ändert. Aus:

Code: Alles auswählen

class Beispiel(object):
    def __init__(self):
        self.wert = 42

beispiel = Beispiel()
beispiel.wert = 23
print beispiel.wert
kann das hier werden:

Code: Alles auswählen

class Beispiel(object):
    def __init__(self):
        self._wert = 32

    @property
    def wert(self):
        return self._wert + 10

    @wert.setter
    def wert(self, value):
        self._wert = value - 10


beispiel = Beispiel()
beispiel.wert = 23
print beispiel.wert
ohne das sich die API von `Beispiel` ändert.

Ob es sich um einen „einfachen” Wert handelt, der dort berechnet wird, ist Abwägungssache. Als Fausregel würde ich sagen wenn es eine Eigenschaft statt einer „Tätigkeit” ist und keinen Zustand verändert und nicht deutlich länger dauert als man das von einem Attributzugriff erwarten würde, dann als `property()`, sonst als Methode mit einem passenden Namen.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

tom1968 hat geschrieben:So eine genormte und ausschließliche Schnittstelle scheint, zumindest auf den ersten Blick, doch eine tolle Sache zu sein
- leichter lesbar und leichter wartbar (z.B. für den Fall dass später mal ein Fall eintritt wo der Wert (erstes Beispiel) generell modifiziert zurückgegeben werden soll ?
Ich halte es für leichter lesbar, wenn kein zusätzlicher Code erforderlich ist um auf das Attribut zugreifen zu können. Eine ggf. später erforderliche Änderung kann in Python, im Gegensatz zu z.B. Java, problemlos durchgeführt werden ohne anderen Code anpassen zu müssen.
tom1968
User
Beiträge: 38
Registriert: Sonntag 30. Juni 2013, 09:54

@tom1968: Ist die Schnittstelle denn bei einfachen Attributzugriffen (also auf das "blanke" `.wert` im Beispiel) unklar? Man kann doch dokumentieren, dass ein Objekt in `.wert` den zugewiesenen Parameter gespeichert hat. Oder geht es dir um read-only-Zugriffe, bei denen der Benutzer nicht nachträglich noch etwas verändern soll?
Es ging mir genrell eher um die Frage was genau mit 'unsäglichen' Gettern und Settern gemeint ist und auch darum inwieweit man direkt in Objekte unter Umgehung von Methoden "reingreifen" soll.
Ich kam auf dieses Thema über die Buchbesprechung "Python 3 lernen und professionell anwenden" von Michael Weigend - dort wurde das kritisiert und ich habe die Seite im Buch gefunden und wollte mich nun nur rückversichern dass ich das richtig verstehe.

@BlackJack
Danke für das Beispiel, wobei mir die Codeersparnis noch nicht so ganz klar ist. Die Methode ist ja nach wie vor vorhanden, was man sich spart ist eigentlich nur dass der Aufruf kürzer ist, also:
beispiel.wert statt beispiel.wert() , ja nach Methodennamen und je nachdem wie oft man diesen Wert braucht mögen die Unterschiede natürlich schon größer sein.
Ich halte es für leichter lesbar, wenn kein zusätzlicher Code erforderlich ist um auf das Attribut zugreifen zu können.....
Mir gehts eher andersrum. Aber gut, das ist jetzt eher theoretisch (bei mir) denn bei dem einen richtigen Progarmmm das ich bisher in Python geschrieben habe kam der Fall nie vor dass ich auf ein einzelnen Wert der Klasse direkt (von außerhalb der Klasse) zurückgreifen mußte.

Thomas
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

tom1968 hat geschrieben:Danke für das Beispiel, wobei mir die Codeersparnis noch nicht so ganz klar ist. Die Methode ist ja nach wie vor vorhanden, was man sich spart ist eigentlich nur dass der Aufruf kürzer ist.
Nein, BlackJack wollte darauf hinaus, dass man Attributszugriffe transparent (also ohne dass der Benutzer es weiss/wissen muss) durch Getter/Setter austauschen kann. Das heisst, dass du dir die Methode sparen kannst, solange du sie nicht brauchst. Es geht nicht um die 2 Klammern ;)
tom1968
User
Beiträge: 38
Registriert: Sonntag 30. Juni 2013, 09:54

Ah ja, ok wenn das so ist, dann macht es auch in meinen Augen Sinn.
Danke für die Erklärung
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

tom1968 hat geschrieben:
Ich halte es für leichter lesbar, wenn kein zusätzlicher Code erforderlich ist um auf das Attribut zugreifen zu können.....
Mir gehts eher andersrum.
Du findest also wirklich, dass dies hier

Code: Alles auswählen

class Foo(object):
    def __init__(self):
        self._value = 0

    @property
    def value(self):
        return self._value
    @value.setter
    def value(self, value):
        self._value = value
leichter zu lesen ist als das hier

Code: Alles auswählen

class Foo(object):
    def __init__(self):
        self.value = 0
?
BlackJack

@tom1968: Die Ersparnis ist bei den ganzen Attributen die sonst triviale Getter/Setter haben würden. Das sind immerhin 3 bis 6 Zeilen pro Attribut (Leerzeilen mitgerechnet). Das macht sich besonders bei Klassen bemerkbar die einzelne „Datensätze” repräsentieren.
tom1968
User
Beiträge: 38
Registriert: Sonntag 30. Juni 2013, 09:54

@/me
Nein, natürlich nicht, wie kommst du darauf ? (Leichter lesbar halte ich es von der Aufrufer Seite her, wenn da eben durchgängig Methoden angesprochen werden und nicht auch manchmal Werte der Klasse/Instanz - aber wie gesagt, es kommt wohl auf den Fall an, BlackJack hat das ja recht anschaulich beschrieben)

@BlackJack
Ja, das verstehe ich, Danke für die Erklärung.

Thomas
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

tom1968 hat geschrieben:Nein, natürlich nicht, wie kommst du darauf ? (Leichter lesbar halte ich es von der Aufrufer Seite her, wenn da eben durchgängig Methoden angesprochen werden und nicht auch manchmal Werte der Klasse/Instanz - aber wie gesagt, es kommt wohl auf den Fall an, BlackJack hat das ja recht anschaulich beschrieben)
Mehr Lesbarkeit durch die Verwerndung von Methoden kann ich ehrlich gesagt nicht erkennen. Bereits an den Namensunterschieden zwischen Attributen und Methoden ist doch in der Regel sofort erkennbar, um was es sich handelt. Attribute sind normalerweise (zusammengesetzte) Nomen, Methoden enthalten typischerweise ein Verb.

Durch die Unterscheidung von Attributen und Methoden wird sogar noch (ein wenig) zusätzliche Information geliefert. Bei einem Methodenaufruf erwarte ich, dass etwas berechnet wird. Bei einem Attributzugriff gehe ich davon aus, dass die Information schon irgendwo vorliegt oder sich sehr einfach aus vorhandenen Werten ableiten lässt. Klar auch hier gibt es Grauzonen, ganz vermeiden lässt sich so etwas natürlich nie.
Das Leben ist wie ein Tennisball.
Antworten