"attribut-decorator" pattern

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
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

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 :)
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.
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

was meinst du mit dynamisch zuweisen? (bin python nubi)
die klassen sind nicht statisch
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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
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.
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

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 :)
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.
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

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 :)
Antworten