Unerwartetes Verhalten einer Klasse

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
Udo
User
Beiträge: 1
Registriert: Samstag 24. März 2018, 17:20

Hallo,

ich bin neu hier und noch Anfänger mit Python.
Ich versuche zu verstehen, was bei der Instanziierung folgender Klasse
passiert. Das Decorator-Prinzip habe ich in etwa verstanden, aber ich
habe mit Google etc. nichts gefunden, was mir folgendes Verhalten
irgendwie erklärt ...

Klassendefinition (Code aus dem Netz - vereinfacht):

Code: Alles auswählen

class Celsius:
    def __init__(self, grad=0):
        self.temperature = grad

    @property
    def temperature(self):
        print("Getting value")
        return self._Temperatur

    @temperature.setter
    def temperature(self, value):
        print("Setter aufgerufen")
        if value < -273:
            raise ValueError("Temperatur unter -273.15 nicht möglich")
        self._Temperatur = value


# Wenn ich jetzt die Klasse auf unterschiedlichem Weg instanziiere,
# erhalte ich unterschiedliche Ergebnisse:

# Instanz T1: korrekt, wie gewünscht
T1 = Celsius(-300)      # Exception wegen des unerlaubten Wertes, wie erwartet

# Instanz T2: nicht korrekt - unerwartet
T2 = Celsius()          # mit Klammern, aber ohne Argument
T2 = -300               # Setter wird aufgerufen, aber keine Exception
print(T2)               # Ausgabe: -300

# Instanz T3: nicht korrekt - ebenfalls unerwartet
T3 = Celsius            # ohne Klammern - nackt!
T3 = -300               # Setter wird nicht aufgerufen, also keine Exception
print(T3)               # Ausgabe: -300
Was passiert hier?
Ich habe in meinen Büchern und im Netz trotz intensiver Suche keine
befriedigende Antwort gefunden.
Wäre jemand so freundlich und würde mir das erklären oder einen Link geben,
damit ich das irgendwie nachvollziehen kann?

Danke und Grüße
Udo
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@Udo: wenn Du Code postest, dann bitte den, der auch das angesprochene Verhalten zeigt. Sonst führt das nur zur Verwirrung.

Code: Alles auswählen

T2 = Celsius()
T2.temperature = -300

T3 = Celsius
T3.temperature = -300
In Python ist alles dynamisch, man kann also auch Klassendefinitionen jederzeit ändern. Das kann dann auch Auswirkungen auf alle existierenden Instanzen haben. Bei `T3` ersetzt Du also das Property `temperature` durch eine konstante Zahl, wobei dann `temperature` als normales Klassenattribute fungiert.

Klarer wird es, wenn Du statt `Celius` in `T3` umzubenennen, `temperature` direkt setzt.

Code: Alles auswählen

>>> T2 = Celsius()
Setter aufgerufen
>>> T2.temperature = -100
Setter aufgerufen
>>> T2.temperature
Getting value
-100
>>> Celsius.temperature = -300
>>> T2.temperature
-300
Du siehst, durch das Überschreiben des Properties ändert sich auch das Verhalten der Instanz `T2`.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Udo hat geschrieben:

Code: Alles auswählen

# Instanz T2: nicht korrekt - unerwartet
T2 = Celsius()          # mit Klammern, aber ohne Argument
T2 = -300               # Setter wird aufgerufen, aber keine Exception
Wie kommst du auf die Idee, dass mit T2 = -300 der Setter des Properties aufgerufen wird? Hier passiert etwas ganz anderes. Vorher war T2 eine Instanz der Celsius-Klasse. Jetzt weist du T2 den Wert -300 zu und die Instanz der Celsius-Klasse ist weg.
Antworten