Python: wie man eine Eigenschaft hat und mit einer setter-Funktion, die alle Änderungen erkennt, die dem Wert passieren

Ich habe zwei Besitzer, die Listen enthält. Wann immer irgend ein Artikel in dieser Liste ändert, würde ich gerne die andere Liste selbst aktualisieren. Dazu gehört die Aussage obj.myProp [3] = 5. Im Moment ruft diese Anweisung die Getterfunktion auf, um die ganze Liste zu erhalten, bekommt das dritte Element aus der Liste und setzt das auf 5. die myProp-Liste wird geändert, aber die zweite Liste wird niemals aktualisiert.

Hier ist mein Code

class grid(object): def __init__(self,width=0,height=0): #make self._rows a multi demensional array #with it's size width*height self._rows=[ [None]*height for i in xrange(width) ] #make self._columns a multi demensional array #with it's size height*width self._columns=[ [None]*width for i in xrange(height) ] @property def rows(self):#getting the rows of the array return self._rows @rows.setter def rows(self,value):#when the rows are changed, the collumns are updated. self._rows=value self._columns=self._flip(value) @property def columns(self):#getting the columns of the array return self._columns @columns.setter def columns(self,value):#when the columns are changed, the rows are updated self._columns=value self._rows=self._flip(value) @staticmethod def _flip(args):#this flips the array ans=[ [None]*len(args) for i in xrange(len(args[0])) ] for x in range(len(args)): for y in range(len(args[0])): ans[y][x] = args[x][y] return ans 

Und hier ist ein Beispiel laufen.

 >>> foo=grid(3,2) >>> foo.rows [[None, None], [None, None], [None, None]] >>> foo.columns [[None, None, None], [None, None, None]] >>> foo.rows=[[1,2,3],[10,20,30]] >>> foo.rows [[1, 2, 3], [10, 20, 30]] >>> foo.columns [[1, 10], [2, 20], [3, 30]] >>> foo.rows[0][0]=3 >>> foo.rows [[3, 2, 3], [10, 20, 30]] >>> foo.columns [[1, 10], [2, 20], [3, 30]] 

Wenn man sich die letzten drei Zeilen ansieht, ist hier das eigentliche Problem aufgetreten. Ich setze den ersten Punkt der Unterliste auf drei, aber foo.columns aktualisiert sich nie, um die 3 in seine Liste zu setzen.

Also kurz gesagt, wie mache ich eine Variable, die immer eine andere Variable aktualisiert, auch wenn sie subitem geändert wird.

Ich benutze python 2.7

3 Solutions collect form web for “Python: wie man eine Eigenschaft hat und mit einer setter-Funktion, die alle Änderungen erkennt, die dem Wert passieren”

Dein Problem ist, dass du keine foo.rows auf die beleidigende Linie setzt – du foo.rows es und modifizierst dann eines seiner Mitglieder. Das wird den Setter nicht abfeuern. Mit der API, die du vorschlägst, musst du eine Liste zurückgeben, die Getter und Setter angefügt hat.

Sie sollten es besser machen, die Zeilen- und __getiten__ nicht zu verwenden, um Einträge einzustellen, und fügen Sie eine __getiten__ Methode wie __getiten__ :

 class grid(object): def __init__(self, width=0, height=0): self._data = [None] * width * height; self.width = width self.height = height def __getitem__(self, pos): if type(pos) != tuple or len(pos) != 2: raise IndexError('Index must be a tuple of length 2') x, y = pos if 0 <= x < self.width and 0 <= y < self.height: return self._data[x + self.width * y] else: raise IndexError('Grid index out of range') def __setitem__(self, pos, value): if type(pos) != tuple or len(pos) != 2: raise IndexError('Index must be a tuple of length 2') x, y = pos if 0 <= x < self.width and 0 <= y < self.height: self._data[x + self.width * y] = value else: raise IndexError('Grid index out of range') @property def columns(self): return [ [self[x, y] for x in xrange(self.width)] for y in xrange(self.height) ] @property def rows(self): return [ [self[x, y] for y in xrange(self.height)] for x in xrange(self.width) ] 

Die gestrichelte Linie wird dann:

 foo[0, 0] = 3 

Wenn Sie einfach Ihre rows oder columns Liste zurückgeben, dann werden Sie nie eine Kontrolle darüber, was passiert, wenn ein Element geändert wird.

Eine Möglichkeit wäre nicht, Eigenschaften zu liefern, um die Listen direkt zu erhalten / einzustellen, aber Setzer / Getter für einen Gegenstand an Position x / y zur Verfügung zu stellen.

Eine nette Version wäre, __setitem__ / __getitem__ zu haben und sie ein Tupel zu akzeptieren, so könntest du die Elemente mit foo[x,y] und foo[x,y] = bar __getitem__ .

Ein anderer Weg wäre, einen Wrapper um die Liste zurückzugeben, der erkennt, ob ein Element geändert wird, aber dann musst du das auch für jede verschachtelte Liste machen.

Ich empfehle Ihnen, mit numpy zu suchen . Insbesondere gibt die Transponierungsmethode eine "Sicht" der zugrunde liegenden Matrix mit den umgesetzten Achsen, dh wenn man sich ändert, dann verändert sich der andere.

Wenn das nicht Ihren Bedürfnissen entspricht, dann ist die einzige Art, wie ich sehen kann, um die API Sie wollen Arbeit zu definieren, die "Zeilen" und "Spalten" Methoden, um benutzerdefinierte "View-Objekte", die nicht wirklich speichern die Daten , Aber das geht auf einige private (geteilte) Daten im Rasterobjekt selbst zurück. Diese könnten listartig sein, würden aber einige Operationen nicht unterstützen (zB anhängen oder löschen).

  • Wann und wie man die eingebaute Funktionseigenschaft () in python benutzt
  • Python - was ist der Unterschied zwischen @property und Einstellung in __init __ ()?
  • Mit @ property Dekorateur auf Dicts
  • Ist es möglich, einen String als Legende in matplotlib hinzuzufügen
  • Wie funktionieren Python-Eigenschaften?
  • Wie man "Superclass-Methoden" in einer Unterklasse "verstecken" kann
  • Python-Eigenschaften & Swig
  • Wie man eine Python-Eigenschaft in __init__
  • Python @property Dekorateur funktioniert nicht
  • Python @property versus Getter und Setter
  • Können Module Eigenschaften auf die gleiche Weise haben, wie Objekte können?
  • Python ist die beste Programmiersprache der Welt.