Seite 1 von 1

Getter und Setter

Verfasst: Donnerstag 12. September 2013, 10:59
von tom1968
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

Re: Getter und Setter

Verfasst: Donnerstag 12. September 2013, 11:21
von snafu
@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?

Re: Getter und Setter

Verfasst: Donnerstag 12. September 2013, 11:41
von 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.

Re: Getter und Setter

Verfasst: Donnerstag 12. September 2013, 12:50
von /me
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.

Re: Getter und Setter

Verfasst: Freitag 13. September 2013, 21:15
von tom1968
@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

Re: Getter und Setter

Verfasst: Freitag 13. September 2013, 21:34
von cofi
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 ;)

Re: Getter und Setter

Verfasst: Freitag 13. September 2013, 21:42
von tom1968
Ah ja, ok wenn das so ist, dann macht es auch in meinen Augen Sinn.
Danke für die Erklärung

Re: Getter und Setter

Verfasst: Freitag 13. September 2013, 22:03
von /me
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
?

Re: Getter und Setter

Verfasst: Freitag 13. September 2013, 22:15
von 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.

Re: Getter und Setter

Verfasst: Samstag 14. September 2013, 18:56
von tom1968
@/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

Re: Getter und Setter

Verfasst: Samstag 14. September 2013, 20:25
von EyDu
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.