[Python-de] getter/setter für python Klassen?

Diez B. Roggisch deets at web.de
Mi Jul 18 10:55:21 UTC 2007


On Wednesday 18 July 2007 12:04, Bastian Venthur wrote:
> Hi Liste,
>
> ich hab irgendwo mal was über getter/setter für Python-Klassen gelesen.
> Irgendwie konnte man
>
> 	instanz.variable = "foo"
>
> machen und intern wurde aber eine Setterfunktion aufgerufen. Sowas
> könnte ich jetzt gut gebrauchen. Weis jemand wie das nochmal ging, bzw.
> wo ich das nachlesen kann? Ich glaube es hatte irgendwas mit Decorators
> zu tun, mit denen hab ich aber bisher noch nie gearbeitet.
>
> Falls es jemanden interessiert warum ich das brauche: Ich hab eine
> Klasse mit einer __str__-Funktion von der ich annehme das sie recht
> teuer ist, da sie einen formatierten String zurück gibt in denen fast
> jede Klassenvariable einmal vorkommt. Diese Funktion wird extrem häufig
> aufgerufen und da habe ich mir überlegt, dass es einfacher ist den
> String einmal zu generieren und dann zwischenzuspeichern um ihn direkt
> zurückzugeben anstatt ihn jedes mal zu generieren. Da der String stets
> aktuell sein muss, müsste er bei jeder Änderung einer Klassenvariable
> neu generiert werden.

Andreas hat die richtige Antwort gegeben bzgl. deiner Ursprungsfrage - wie man 
properties macht.

Aber dein Usecase ist in diesem Fall IMHO nicht geeignet. Denn letztlich 
machst du dir sehr, sehr viel arbeit auf die Weise.

Stattdessen solltest mit __getattr__/__setattr__ arbeiten. Damit kannst du ein 
dirty-flag setzten wann immer du einen Wert setzt - und daraufhin dein 
gecachten String neu rendern.

In etwa so (aussem Kopp):

class Foo(object):

   def __init__(self):
        d = self.__dict__ # das brauchn wir, weil __setattr__ ueberladen ist
        d['_dirty'] = True
        # ab jetzt ist alles ok...
        self.foo = "bar"

    def __getattr__(self, name):
        return self.__dict__[name]

    def __setattr__(self, name, value):
         self._dirty = True
         self.__dict__[name] = value

    def __str__(self):
         if self._dirty:
            self._str = berechne_str()
            self._dirty = False
         return self._str


Diez