Wozu braucht man Setter und Getter?

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
NoBody2
User
Beiträge: 12
Registriert: Mittwoch 8. November 2017, 01:49

Ich lerne gerade Python und da wo ich es lerne werden gerade Setter und Getter erklärt. Aber ich verstehe das nicht. Das verwendete Beispiel-Programm:

Code: Alles auswählen

class A:
    def __init__(self):
        self._X = 100

    def getX(self):
        print("Getter gerufen")
        return self._X

    def setX(self, wert):
        print("Setter gerufen")
        if wert < 0:
            return
        self._X = wert

    X = property(getX, setX)


a = A()
print(a.X)
a.X = 300
print(a.X)
a.X = -20
print(a.X)
Meine Frage ist jetzt, warum sollte man einen Setter und Getter definieren, anstatt einfach mit a._X darauf zuzugreifen? Das ganze ergibt keinen Sinn.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

NoBody2 hat geschrieben:[Getter & Setter] Das ganze ergibt keinen Sinn.
Sehr richtig erkannt. Getter und Setter sind ursprünglich ein Hack in Java, den man aber in Python nicht braucht. Sie sind unpythonisch und man sollte sie nicht verwenden. Ein Buch, in dem steht, man solle in Python Getter und Setter schreiben, gehört ins Altpapier.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

NoBody2 hat geschrieben:[Getter & Setter] Das ganze ergibt keinen Sinn.
Sehr richtig erkannt. Getter und Setter sind ursprünglich ein Hack in Java, den man aber in Python nicht braucht. Sie sind unpythonisch und man sollte sie nicht verwenden. Ein Buch, in dem steht, man solle in Python Getter und Setter schreiben, gehört ins Altpapier.

In deinem Code stehen aber keine Getter und Setter (obwohl sie so genannt werden), sondern Properties. Leider wird dort nicht gezeigt, wie sie seit allerneuestem (in drei Wochen werden es 13 Jahre) definiert werden:

Code: Alles auswählen

class A:
    def __init__(self):
        self._x = 100

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, wert):
        if wert < 0:
            return
        self._x = wert

a = A()
print(a.x)
a.x = 300
print(a.x)
a.x = -20
print(a.x)
Der Sinn von Properties ist folgender. Gegeben diese Klasse:

Code: Alles auswählen

class A:
    def __init__(self):
        self.x = 100
Angenommen nun hunderte von Codestellen, an denen auf A-Objekten das x-Attribut gesetzt wird, also sowas:

Code: Alles auswählen

a = A()
...
a.x = some_value
...
Nun kommt jemand und möchte, dass x nie negativ werden darf. Dann musst du um jede Zuweisung (hunderte!) einen Test wickeln:

Code: Alles auswählen

a = A()
...
if some_value >= 0:
   a.x = some_value
...
Und wehe, du übersiehst eine Stelle, dann ist dein Programm kaputt.

Oder du änderst die Klasse und ersetzt jede Zuweisung durch einen Methodenaufruf:

Code: Alles auswählen

class A:
    def __init__(self):
        self._x = 100

    def get_x(self):
        return self._x

    def set_x(self, wert):
        if wert < 0:
            return
        self._x = wert

...
a = A()
...
a.set_x(123)  # x ist jetzt 123
...
a.set_x(-999) # x ist immer noch 123
Auch hier musst du also jede Zuweisung ändern.

Wenn du statt dessen die einfache Klasse A in eine mit Properties änderst, kann der restliche Code bleiben, wie er ist, und der Test wird trotzdem überall durchgeführt.

PS: Die Lösch-/Editierzeit für Posts ist definitiv zu kurz.
In specifications, Murphy's Law supersedes Ohm's.
NoBody2
User
Beiträge: 12
Registriert: Mittwoch 8. November 2017, 01:49

Achso, habs verstanden, danke
Antworten