Seite 1 von 1

Handler je nach Klasse

Verfasst: Sonntag 1. September 2013, 16:25
von sprudel
Hallo,
ich möchte für ein kleines Pluginsystem verschiedene Handler für meine Programme ermöglichen. Ich habe eine Grundklasse, von der jede Klasse meines Programms (Product, Transaction, etc.) abgeleitet wird.

Diese ist im Konkreten so aufgebaut:

Code: Alles auswählen

class CPClass(object):
    id = None
    actions = {"init": []}
    
    @reconstructor
    def __init__(self,**kwargs):
        for key,value in kwargs.iteritems():
            setattr(self,key,value)
    
    @hybrid_method
    def search(cls,condition=None,**kwargs):
        if condition:
            return session.query(cls).filter(condition)
        else:
            return session.query(cls).filter_by(**kwargs)
    
    @hybrid_method
    def search_one(cls,condition=None,**kwargs):
        return cls.search(condition=condition,**kwargs).one()
    
    @classmethod
    def on(cls,action,handler):
        try:
            cls.actions[action].append(handler)
        except KeyError:
            cls.actions[action] = list()
            cls.actions[action].append(handler)
Die abgeleiteten Klassen werden dann ebenso von "Base" aus Sqlalchemy abgeleitet. Das Ganze funktioniert soweit ganz gut.
Nun habe ich aber das Problem, dass wenn ich zum Beispiel auf das abgeleitete "Transaction" mittels on einen Handler registriere, dieser für alle anderen Klassen ebenso registriert ist, nicht nur für Transaction. Nach meiner Auffassung müsste das ja dann nur in Transaction.actions abgespeichert werden, wird so nun aber in CPClass.actions hinterlegt.

Wo habe ich da meinen Denkfehler?

Vielen Dank.

Re: Handler je nach Klasse

Verfasst: Sonntag 1. September 2013, 16:34
von EyDu
Hallo.

Ja, du hast da einen Denkfehler:

Code: Alles auswählen

>>> class Base(object):
...     actions = []
... 
>>> class Spam(Base): pass
... 
>>> class Eggs(Base): pass
... 
>>> id(Base.actions)
140671944032408
>>> id(Spam.actions)
140671944032408
>>> id(Eggs.actions)
140671944032408
Alle Klassen teilen sich "actions". Wenn du ein actions-Attribute pro Klasse willst, dann musst du dies auch explizit erstellen.

Edit: Und schau dir mal ``collections.defaultdict`` an, damit wird die on-Funktion zu einem Einzeiler.

Re: Handler je nach Klasse

Verfasst: Sonntag 1. September 2013, 16:37
von sprudel
Vielen Dank, das war mir so nicht bewusst :-) Sehe ich es also richtig, dass ich die on-Methode behalten kann, aber dafür actions jedes Mal explizit festlegen muss?

Re: Handler je nach Klasse

Verfasst: Sonntag 1. September 2013, 16:37
von Sirius3
Wie kommst Du auf die Idee, dass auf magische Weise das Attribut »CPClass.actions« nach »Transaction.actions« wandert? Es wird einmal beim Erstellen der Klasse »CPClass« erzeugt und ihm ein Dictionary (was besser wohl ein »collections.defaultdict« wäre) zugewiesen.

Re: Handler je nach Klasse

Verfasst: Sonntag 1. September 2013, 16:40
von EyDu
sprudel hat geschrieben:Sehe ich es also richtig, dass ich die on-Methode behalten kann, aber dafür actions jedes Mal explizit festlegen muss?
Wenn ich dich richtig verstanden habe, dann ja.

Re: Handler je nach Klasse

Verfasst: Sonntag 1. September 2013, 16:40
von sprudel
War wohl eine grundsätzliche Verständnisfrage, ich betrachtete das Ableiten (vererben) im Grunde nur als eine Kopie der Ursprungsklasse, im Grunde nur eine 1:1-Kopie des Programmcodes. Verstehst du wie ich meine?

Re: Handler je nach Klasse

Verfasst: Sonntag 1. September 2013, 16:47
von BlackJack
@sprudel: Nur das es eben keine Kopie ist. Das wäre auch etwas unökonomisch Kopien zu erzeugen die dann ja gleich sind, statt das bereits vorhandene zu verwenden.