Seite 1 von 1

Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 09:14
von schneitzmaster
Hallo Leute,

ich habe mal wieder ein Problem beim Erzeugen von Klassen.
Nach etwas Recherche habe ich eine Vorstellung was Klassen, Objekte, Attribute und Methoden sind. Nun will ich eine Klasse erzeugen bei dem ein Klassen Attribut von anderen abhängt und dann auch dynamisch seinen Wert ändern soll. Hier mein versuchtes Minimalbeispiel:

Code: Alles auswählen

class mainClass():
    def __init__(self):
        self.a = 3.0
        self.b = 2.0
        self.c = self.a * self.b
                
obj = mainClass()
print obj.c
obj.a = 4.0
obj.b = 5.0
print obj.c   
Am ende sollte eigentlich 20.0 da stehen. Leider bleibt der wert auf 6.0. Gibt es eine möglichkeit die Attribute der mainClass zu aktualisieren oder ist mein Ansatz falsch?

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 09:22
von BlackJack
@schneitzmaster: Es gibt eine Möglichkeit und zwar mit `property()`. Das funktioniert aber nur zuverlässig wenn die Klasse von `object` erbt, was man in Python 2.x grundsätzlich machen sollte, wenn es keine andere Basisklasse gibt.

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 09:38
von /me
Um den Vorschlag von BlackJack mal in Code zu gießen:

Code: Alles auswählen

class Main1(object):
    def __init__(self, a=0.0, b=0.0):
        self.a = a
        self.b = b

    def c(self):
        return self.a * self.b

test = Main1(3.0, 2.0)
print(test.c())
test.a = 4.0
test.b = 5
print(test.c())

class Main2(object):
    def __init__(self, a=0.0, b=0.0):
        self.a = a
        self.b = b

    @property
    def c(self):
        return self.a * self.b

test = Main2(3.0, 2.0)
print(test.c)
test.a = 4.0
test.b = 5
print(test.c)
Die erste Variante ist "klassisch", die zweite mit dem property-Dekorator. Den Unterschied sieht man dann beim Aufruf.

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 09:38
von schneitzmaster
Super. Danke für den Tip. Ich hab unter folgendem linke eine gute Anleitung gefunden (http://www.itmaybeahack.com/book/python ... rties.html).
Das probiere ich mal.

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 09:50
von schneitzmaster
Hi /me danke für deinen Vorschlag.
Ich hab mich auch mal dran versucht und habe eine ähnliche Variante gefunden.
Ist die verwertbar oder kommt nur zufällig das heraus was ich will?

Code: Alles auswählen

class mainClass(object):
    def __init__(self):
        self.a = 3.0
        self.b = 2.0
    def varc_set( self ):
        return self.a * self.b
    c = property(varc_set)
    
          
obj = mainClass()
print obj.c
obj.a = 4.0
obj.b = 5.0
print obj.c
Welche Vorteile bringt es @property zu verwenden?

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 09:58
von BlackJack
@schneitzmaster: Die @-Syntax ist besser lesbar weil man Anfang schon sieht dass es sich um ein `property()` handelt und nicht erst nachdem man zum Beispiel alle drei Methoden implementiert hat. Insbesondere wenn die Methoden nicht nur aus einer Zeile bestehen. `property()` ist mit ein Grund warum die @-Syntax überhaupt eingeführt wurde.

Der Name Deiner Methode für das `property()` ist übrigens falsch. Es get weder um ein `varc` (was soll das sein?[1]) noch wird da etwas gesetzt.

[1] Ich kann mir natürlich denken was damit gemeint ist, aber man kann das mit einem Unterstrich deutlicher machen.

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 10:00
von /me
schneitzmaster hat geschrieben:Welche Vorteile bringt es @property zu verwenden?
Es ist eine andere Syntax die erst nach dem built-in property eingeführt wurde.

Der Name varc_set für eine Methode die ein get auf ein Attribut c durchführt ist übrigens äußerst verwirrend.

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 10:04
von schneitzmaster
Also das varc_set sollte nur für "Variable c set" stehen. Ich hatte nicht tiefer drüber nach gedacht und wollte nur anzeigen das diese funktion der Variablen c einen Wert gibt.
@ BlackJack: So wie ich das verstanden habe wird doch genau in dieser Funktion etwas gesetzt nämlich der Wert für die Variable c bzw. ist diese Funktion für den Prozess der Wertzuweisung für c da, oder?

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 10:26
von EyDu
Hallo.

Nein, die Methode varc_set setzt kein Attribut c. Da ändert auch der property-Aufruf nichts dran. Es wird lediglich immer die Methode varc_set aufgerufen, wenn du das Attribut c abfragst. Bei jedem Zugriff auf c wird daher das Ergebnis neu berechnet.

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 10:28
von /me
schneitzmaster hat geschrieben:Also das varc_set sollte nur für "Variable c set" stehen. Ich hatte nicht tiefer drüber nach gedacht und wollte nur anzeigen das diese funktion der Variablen c einen Wert gibt.
Wenn ich eine Funktion aufrufe erwarte ich eine Übereinstimmung des Namens mit dem, was ich von der Funktion möchte und nicht mit dem, was eventuell intern abläuft.

Du möchtest den Wert c haben, also wäre c_get oder auch _c_get ein geeigneter Name. Wenn du dir deinen Code mal anschaust wirst du zudem feststellen, dass es gar keine Variable c gibt, deren Wert irgendwo gesetzt würde. Der Wert wird bei jedem Aufruf dynamisch ermittelt.

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 10:31
von schneitzmaster
Alles klar verstehe. Nur noch mal für mich zum mithämmern: Ich hätte die Funktion also auch c_dynamischBerechnen nennen können.
Langsam steige ich dahinter.
Danke noch mal

Re: Dynamische Attribut/Variablenänderung in Klassen

Verfasst: Donnerstag 24. Januar 2013, 10:38
von /me
schneitzmaster hat geschrieben:Alles klar verstehe. Nur noch mal für mich zum mithämmern: Ich hätte die Funktion also auch c_dynamischBerechnen nennen können.
Ja, hättest du.

Um die Möglichkeiten aufzuzeigen habe ich noch mal ein kleines Beispiel mit Getter und Setter geschrieben (unter Verwendung der Dekorator-Syntax).

Code: Alles auswählen

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

    @property
    def value(self):
        return self._value
    @value.setter
    def value(self, value):
        if not 0 <= value <= 10:
            raise ValueError('Invalid value {}'.format(value))
        self._value = value

test = Test()
print(test.value)
test.value = 7
print(test.value)
test.value = 11
In der letzten Zeile wird dann eine Exception geworfen, da die Prüfung beim versuchten Setzen des Wertes nicht erfolgreich war.