Property zur Laufzeit generieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
moesibaer
User
Beiträge: 16
Registriert: Donnerstag 27. Dezember 2007, 15:54
Kontaktdaten:

Hallo,

ich möchte in meiner Klasse die Property Objekte zur Laufzeit generieren. Hier der aktuelle Code, der eine übergebenes SQLObjekt durchläuft und aus seinen properties die meiner Klasse macht. Diese will ich dann teilweise in meiner Klasse überschreiben um bei den Settern einige Überprüfungen durchzuführen, bevor der Wert in die Datenbank kommt. Die anderen sollen durch die lambda Funktion gesperrt werden.

Code: Alles auswählen


def GetSetterName(name):
    return "_set_%s" % name
def GetGetterName(name):
    return "_get_%s" % name
def GetPropertyName(name):
    return name

class MyObjekt(object):
_obj = None #speichert das Resultat von get
_table = None
_name = None

def __init__(self,table,name):    
        self._table = table
        self._name = name

       #sqlobject durchlaufen
        for name,item in table.__dict__.iteritems():
            #fuer jedes property im sqlobject
            #ein eigenes in dieser klasse schalten
            if isinstance(item,property):
                getter = lambda self,value: eval("self._obj.%s" % name)
                setter = lambda self,value: False #Standard soll sein, den Setter fuer das SQLOBjekt zu verbieten, wo es erlaubt ist soll das property ueberschrieben werden
                setattr(self, GetSetterName(name), setter)
                setattr(self, GetGetterName(name), getter)
                setattr(self, GetPropertyName(name), property(setter,getter))

class User(MyObject):
    def __init__(self):
        super(User, self).__init__(UserTable,"User")

Problem ist nun das ich folgende Ausgabe bekomme

Code: Alles auswählen

>>>a = User()
>>>a.get(1) #holt sich aus der Tabelle die spalte mit der ID 1, ist nicht im Code oben drin
>>>a.name
<property object at 0x833ad4c>
In wie weit geh ich das falsch an?

Danke für jede Hilfe!
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Propertys werden Deskriptoren sein, und die müssen im Klassendictionary sein und nicht im Dictionary vom Klassenexemplar (siehe Referenz). Du müsstest also jedes Mal eine neue Klasse mit den jeweiligen Propertys erstellen und davon ein Exemplar erstellen.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Überschreib einfach __getattr__ und __setattr__, du machst dir das zu kompliziert.

Ich bau grad nen Beispiel
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

class Foobar(object):

    def _locked(self, *args):
        raise AttributeError, "Property is locked"

    def __getattr__(self, value):
        return object.__getattribute__(self, "get_%s" % value).__call__(self)

    def __setattr__(self, value, item):
        return object.__getattribute__(self, "set_%s" % value).__call__(self, item)

    def lock(self, value):
        func = getattr(self, "set_%s" % value)
        if func != self._locked:
            object.__setattr__(self, "_set_%s" % value, func)
            object.__setattr__(self, "set_%s" % value, self._locked)
        else:
            object.__setattr__(self, "set_%s" % value,
                object.__getattribute__(self, "_set_%s" % value))

    def init(self, value):
        object.__setattr__(self, "get_%s" % value,
            lambda self, : object.__getattribute__(self, value))
        object.__setattr__(self, "set_%s" % value,
            lambda self, item: object.__setattr__(self, value, item))

if __name__ == "__main__":
    foo = Foobar()
    foo.init("bar")
    foo.bar = "baz"
    print foo.bar
    foo.lock("bar")
    try:
       foo.bar = "foobar"
    except AttributeError, e:
        print e
    print foo.set_bar
    foo.lock("bar")
    print foo.set_bar
    print foo._set_bar
    foo.bar = "bubu"
    print foo.bar

Code: Alles auswählen

baz
Property is locked
<bound method Foobar._locked of <__main__.Foobar object at 0x4032772c>>
<function <lambda> at 0x40319224>
<function <lambda> at 0x40319224>
bubu
moesibaer
User
Beiträge: 16
Registriert: Donnerstag 27. Dezember 2007, 15:54
Kontaktdaten:

ah korrekt, herzlichen Dank, das ist ne Gute Sache! Vielen Dank für das Beispiel!
Antworten