Im Klassenobjekt, wie man Auto-Attribute automatisch aktualisiert?

Ich habe eine Klasse, die mehrere Attribute, die verwandt sind, zum Beispiel:

class SomeClass: def __init__(self, n=0): self.list = range(n) self.listsquare = [ x**2 for x in self.a ] 

Wenn ich ein Objekt normal mache, wäre das kein Problem

 a = SomeClass(10) 

Ich bekomme 2 Listen, a.list und a.listsquare .

Nun, wenn ich zuerst ein leeres Objekt machen und ihm ein Attribut zuordnen möchte, möchte ich, dass die anderen Attribute automatisch aktualisiert werden, zB wenn ich es tue

 b = SomeClass() b.list = range(5,10) 

Ich möchte, dass b.listsquare automatisch aktualisiert wird, und auch umgekehrt (zuweisen b.listsquare und auto update b.list ). Ist das möglich? Ist die Klasse die richtige Wahl dafür?


Danke euch allen, aber ich bin ganz von allen verschiedenen Antworten überwältigt. Kann jemand eine komplette Lösung geben, damit ich lernen kann, meine eigenen zu schreiben?

Ich möchte eine Klasse Foo mit 3 Attributen length , list und listsquare so dass:

  1. Wenn ich a = Foo(3) a.length = 3 , a.list = [0, 1, 2] ich a.length = 3 , a.list = [0, 1, 2] , a.listsquare = [0, 1, 4] .
  2. Wenn ich b = Foo().list = [5, 6] bekomme ich b.length = 2 , b.listsquare = [25, 36] .
  3. Wenn ich c = Foo().listsquare = [4, 9] c.length = 2 , c.list = [2, 3] ich c.length = 2 , c.list = [2, 3] .

4 Solutions collect form web for “Im Klassenobjekt, wie man Auto-Attribute automatisch aktualisiert?”

Wenn Sie eine Eigenschaft aufgrund eines Updates auf einer anderen Eigenschaft aktualisieren, ist das, was Sie suchen (anstatt den Wert der Downstream-Eigenschaft beim Zugriff neu zu berechnen)

 class SomeClass(object): def __init__(self, n): self.list = range(0, n) @property def list(self): return self._list @list.setter def list(self, val): self._list = val self._listsquare = [x**2 for x in self._list ] @property def listsquare(self): return self._listsquare @listsquare.setter def listsquare(self, val): self.list = [int(pow(x, 0.5)) for x in val] >>> c = SomeClass(5) >>> c.listsquare [0, 1, 4, 9, 16] >>> c.list [0, 1, 2, 3, 4] >>> c.list = range(0,6) >>> c.list [0, 1, 2, 3, 4, 5] >>> c.listsquare [0, 1, 4, 9, 16, 25] >>> c.listsquare = [x**2 for x in range(0,10)] >>> c.list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

Unbedingt. Verwenden Sie stattdessen eine Eigenschaft .

 class SomeClass(object): def __init__(self, n=5): self.mylist = range(n) @property def listsquare(self): return [ x**2 for x in self.mylist ] a = SomeClass() a.mylist = [4, 5, 8] print a.listsquare 

Das Caching des Eigenschaftswertes bleibt als Übung für den Leser übrig.

Sie können auch einfach Setter Methoden, wie folgt:

 class SomeClass: def __init__(self, n=5): self.set_list(range(n)) def set_list(self, n): self.list = n self.listsquare = [ x**2 for x in self.list ] b = SomeClass() b.set_list(range(5,10)) 

Ignacios @property-Lösung ist großartig, aber es rechnet die Liste jedes Mal, wenn Sie auf listsquare – das könnte teuer werden. Mathews Lösung ist großartig, aber jetzt hast du Funktionsaufrufe. Sie können diese mit der Funktion 'Eigenschaft' kombinieren. Hier definiere ich einen Getter und einen Setter für meine_list (ich konnte einfach nicht nennen es 'list'!), Die listsquare erzeugt:

 class SomeClass(object): def __init__(self, n=5): self.my_list = range(n) def get_my_list(self): return self._my_list def set_my_list(self, val): self._my_list = val # generate listsquare when my_list is updated self.my_listsquare = [x**2 for x in self._my_list] # now my_list can be used as a variable my_list = property(get_my_list, set_my_list, None, 'this list is squared') x = SomeClass(3) print x.my_list, x.my_listsquare x.my_list = range(10) print x.my_list, x.my_listsquare 

Diese Ausgänge:

 [0, 1, 2] [0, 1, 4] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 
Python ist die beste Programmiersprache der Welt.