Klasse dynamisch subklassieren...

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.
Red Rooster
User
Beiträge: 12
Registriert: Donnerstag 8. November 2012, 13:30

Freitag 9. November 2012, 16:53

BlackJack hat geschrieben:@Red Rooster: Ich sehe nicht warum Du keinen Proxy daraus machen können solltest. Das Entwurfsmuster zeichnet sich ja dadurch aus, dass es nach aussen wie der Datentyp verhält, für den es als Stellvertreter und Vermittler steht. Gerade bei dynamischer Typisierung geht so etwas doch sehr problemlos durch. Das hier ist deutlich weniger magisch als was Du da versuchst:

Code: Alles auswählen

class MyDB(object):
    def __init__(self, engine):
        self.db = Database(engine)
    
    def __getattr__(self, name):
        return getattr(self.db, name)
    
    def select(self):
        print 'select for MyDB, backed by:',
        self.db.select()
Zusätzlich könnte man `Database` hier auch durch eine Fabrikfunktion ersetzen um das `__new__()` los zu werden.
Danke! Jetzt sehe ich, was Du meinst. Dann sollte ich wohl gleich aus Database eine Proxy-Klasse machen, das __new__ rausschmeißen und dann kann ich auch MyDB wieder ohne Problem von Database ableiten!
Ich hatte gar nicht gewußt, daß man __getattr__ auf eine beliebige Klasse umleiten kann! :o
Red Rooster
User
Beiträge: 12
Registriert: Donnerstag 8. November 2012, 13:30

Freitag 9. November 2012, 17:35

Red Rooster hat geschrieben:
BlackJack hat geschrieben:@Red Rooster: Ich sehe nicht warum Du keinen Proxy daraus machen können solltest. Das Entwurfsmuster zeichnet sich ja dadurch aus, dass es nach aussen wie der Datentyp verhält, für den es als Stellvertreter und Vermittler steht. Gerade bei dynamischer Typisierung geht so etwas doch sehr problemlos durch. Das hier ist deutlich weniger magisch als was Du da versuchst:

Code: Alles auswählen

class MyDB(object):
    def __init__(self, engine):
        self.db = Database(engine)
    
    def __getattr__(self, name):
        return getattr(self.db, name)
    
    def select(self):
        print 'select for MyDB, backed by:',
        self.db.select()
Zusätzlich könnte man `Database` hier auch durch eine Fabrikfunktion ersetzen um das `__new__()` los zu werden.
Danke! Jetzt sehe ich, was Du meinst. Dann sollte ich wohl gleich aus Database eine Proxy-Klasse machen, das __new__ rausschmeißen und dann kann ich auch MyDB wieder ohne Problem von Database ableiten!
Ich hatte gar nicht gewußt, daß man __getattr__ auf eine beliebige Klasse umleiten kann! :o
Zuletzt geändert von Red Rooster am Freitag 9. November 2012, 17:55, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4872
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Freitag 9. November 2012, 17:46

Sagt doch die Fehlermeldung aus: self.db existiert in Database.select nicht, also wird __getattr__ aufgerufen. Das versucht auf dem Objekt self.db, welches es natürlich nicht gibt, etwas zu machen. Also wird __getattr__ aufgerufen um self.db zu finden. Den Rest kannst du dir ja vorstellen.
Das Leben ist wie ein Tennisball.
Red Rooster
User
Beiträge: 12
Registriert: Donnerstag 8. November 2012, 13:30

Freitag 9. November 2012, 17:56

EyDu hat geschrieben:Sagt doch die Fehlermeldung aus: self.db existiert in Database.select nicht, also wird __getattr__ aufgerufen. Das versucht auf dem Objekt self.db, welches es natürlich nicht gibt, etwas zu machen. Also wird __getattr__ aufgerufen um self.db zu finden. Den Rest kannst du dir ja vorstellen.
Danke! Jetzt seh' ich den Wald vor lauter Bäumen nicht mehr... Ich mach' Feierabend für heute.
EyDu
User
Beiträge: 4872
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Freitag 9. November 2012, 17:57

Ach, das ist sicher schon jedem mal mit __getattr__ passiert. Irgendwann denkt man halt dran ;-)
Das Leben ist wie ein Tennisball.
Antworten