Seite 1 von 1

"attribut-decorator" pattern

Verfasst: Freitag 23. Februar 2007, 22:10
von Dill
Hi,


mit dem decorator pattern kann man sich ja schön objekte zusammenbasteln, die dann eine "zusammengesetzte" methode besitzen.

Wie ist es möglich auf ähnliche art ein objekt zu bauen, das aus einer menge von attributen nur bestimmte besitzt?

konkret geht es um komponenten mit bestimmten eigenschafen. (Es gibt 12 versch. komponenten)

- alle haben namen und id. (class Component)
- manche eine adresse (class Physical)
- manche ein zugeordnetes symbol (class Represented)
usw.

Ich möchte verhindern für jede Komponente eine eigene klasse zu schreiben.
schöne wäre so etwas:

Code: Alles auswählen


foo = Physical( Represented( Component( name, uid ), symbol ), address )

#und gleichzeitig sollte auch gehen:

foo = Represented( Physical( Component( name, uid ), address ), symbol )

#und ich kann einfach zugreifen auf

foo.name
foo.uid
foo.symbol
foo.address


entweder ich stehe voll aufm schlauch, oder das ist mit den mir bekannten pattern nicht möglich.

danke für eure anregungen :)

Verfasst: Freitag 23. Februar 2007, 23:03
von BlackJack
Kannst Du nicht einfach dynamisch die gewünschten Attribute zuweisen? Es sieht so aus als wenn Du dynamische Daten als mehr oder weniger statische Klassen darstellen willst.

Verfasst: Freitag 23. Februar 2007, 23:55
von Dill
was meinst du mit dynamisch zuweisen? (bin python nubi)
die klassen sind nicht statisch

Verfasst: Samstag 24. Februar 2007, 09:38
von EyDu
Für mich hört sich das nach Mehrfachvererbung an. Hier ein kleines Beispiel, aber es ist nur zu empfehlen sich in das Thema einzuarbeiten:

Code: Alles auswählen

class Component:
    def __init__(self):
        self.component_attr1 = 1
        self.component_attr2 = 2

class Physical:
    def __init__(self):
        self.physical_attr1 = 3
        self.physical_attr2 = 4

class Represented:
    def __init__(self):
        self.represented_attr1 = 5
        self.represented_attr2 = 6

class CompAndPhys(Component, Physical):
    def __init__(self):
        Component.__init__(self)
        Physical.__init__(self)
        #Und noch eigene Attribute

class CompAndRepr(Component, Physical):
    def __init__(self):
        Component.__init__(self)
        Represented.__init__(self)
        #Und noch eigene Attribute

Verfasst: Samstag 24. Februar 2007, 09:42
von BlackJack
Irgendwann musst Du ja entscheiden welche Attribute an ein konkretes Objekt gebunden werden sollen. Und an der Stelle machst Du dass dann einfach. Bis jetzt war in Deiner Anforderung noch nichts was dagegen spräche, es kann aber durchaus sein, dass es nicht so einfach geht.

Verrate doch mal ein bisschen mehr, und am besten nicht wie Du das Problem lösen willst, sondern einfach erstmal nur was für ein Problem gelöst werden soll.

Und prüfe mal ob sich das Problem auch durch Komposition statt Vererbung lösen lässt.

Verfasst: Samstag 24. Februar 2007, 11:27
von Dill
Für mich hört sich das nach Mehrfachvererbung an.
nein, das möchte ich verhindern.
da die einzelnen klassen ihre attribute frei aus 8 verschiedenen attributen kombinieren können hätte ich dann worst case 2^8 klassen zu schreiben ...
Und prüfe mal ob sich das Problem auch durch Komposition statt Vererbung lösen lässt.
nein das wäre unschön.

Irgendwann musst Du ja entscheiden welche Attribute an ein konkretes Objekt gebunden werden sollen. Und an der Stelle machst Du dass dann einfach.
JA! aber das muss einem erstmal klar werden ...
also dynamisch zuweisen :)

Code: Alles auswählen

>>> class test:
...     def __init__(self, a):
...             self.a = a
...
>>> t=test(1)
>>> dir(t)
['__doc__', '__init__', '__module__', 'a']
>>> t.b=2
>>> dir(t)
['__doc__', '__init__', '__module__', 'a', 'b']

und dann könnte man irgendwie so die klassen mergen:

Code: Alles auswählen


foo = Represented( Component( name, uid ), symbol )

class Component:
   def __init__(s, name, id):
       s.name = name
       s.uid = uid
   # component methoden

class Represented:
   def __init__(s, deco, symbol):
       s.symbol = symbol
       for attr in set(dir(deco)) - set(dir(s)):
             setattr( s, attr, getattr(deco, attr) )


habe ich jetzt noch nicht getestet, aber so in der art soll das laufen...
teste das mrogen mal, heute keine zeit.
problem werden methoden sein, vor allem die, die eigentlich über den dekorator fusioniert werden müssen ...


danke für eure hilfe :)

Verfasst: Samstag 24. Februar 2007, 11:44
von BlackJack
Für mich sieht das immer mehr nach Komposition aus.

Auf jeden Fall würde ich das nicht in `__init__()`-Methoden unterbringen, sondern eine Factory-Funktion schreiben, die mehrere Objekte entgegennimmt und diese dynamisch zu einem neuen Objekt zusammensetzt oder eines um die Attribute der anderen ergänzt.

Verfasst: Samstag 24. Februar 2007, 12:05
von Dill
nein, es ist keine komposition. aber damit du mir das glaubst müsste ich dir zuviel kram über das system erzählen der dich nicht interessiert :)

sicher das wird in eine factoy ausgelagert.

danke, mein problem ist jetzt gelöst denke ich :)