Magische Funktionen in Python (get, set)


ZodiacXP

Erfahrenes Mitglied
Hallo. Ich möchte eine Variable in einer Klasse haben und dynamische getter / setter (Python 2.5):
Python:
import string

class Template:
    '''
    classdocs
    '''
    htmlText = ""
    _value = {}

    def __init__(self, template):
        '''
        Constructor
        '''
        f_in = open(template, "r")
        self.htmlText = f_in.read()
        f_in.close()
    
    def __getattr__(self, name):
        return self._values[name]
    
    def __setattr__(self, name, value):
        self._values[name] = value
        
    def __str__(self):
        r = self.htmlText
        for key in self._value.iterkeys():
            r = string.replace(
                               r,
                               "<% #" + key + "%>",
                               self._values[key]
                               )
        return r

Kann mir jemand erklären, warum Python damit Probleme hat und wie man trotz getter/setter vorhandene Objektvariablen nutzen kann?
 

deepthroat

Erfahrenes Mitglied
Hi.

Evtl. solltest du mal sagen worin das Problem besteht?!

Vielleicht hat es damit zu tun, das du die Klassenvariable _value genannt hast, aber versuchst auf die Variable _values zuzugreifen... ?

Gruß
 

ZodiacXP

Erfahrenes Mitglied
Oh. Das fehlende "s" ist vorhin abhanden gekommen.

Es ist so, dass keine Ausgabe erfolgt, wenn man ein Template nimmt:
Code:
<body><% #tst %>

und das dann verarbeitet:
Python:
t = HTMLTemplate("template.html")
t.tst = "Foo"
req.write(str(t))

t.tst kann man sich einzeln ausgeben lassen. Aber das ganze als String nicht. Die Funktion dazu habe ich nun etwas abgeändert, effekt bleibt:
Python:
    def __str__(self):
        r = self.htmlText
        for key in self._values.keys():
            r  = r.replace(
                           "<% #" + key + "%>",
                           self._values[key]
                           )
 

deepthroat

Erfahrenes Mitglied
Hi.

Das erste Problem ist, dass du im Konstruktor den Text des Templates über self.htmlText setzt, wobei die __setattr__ Methode aufgerufen wird und nicht die Klassenvariable verändert wird. Nachher greifst du auf self.htmlText zu, allerdings wird da nicht __getattr__ aufgerufen, da es ein Klassenattribut gibt.

Das zweite Problem ist, das _values auch ein Klassenattribut ist und du so nicht mehrere Instanzen unabhängig voneinander erstellen kannst.

Schau mal hier: http://code.activestate.com/recipes/389916/

Gruß