Innpakning og synkronisering messenger klasse i python

stemmer
0

Jeg ønsker å skape en struktur med en budbringer klasse som er delt mellom flere andre klasser. Jeg ønsker å holde parametere synkronisert mellom messenger og underklasser, og jeg ønsker også sub-klasser for å kunne få tilgang til hverandre via messenger. Jeg har for tiden implementert det som følger, men jeg har noen problemer med synkroniseringen:

class MessengerWrapper:
     def __getattribute__(self,attr):
         #Force use of custom getattr
         return self.__getattr__(self,attr)

     def __getattr__(self,attr):

         #return the messenger if asking for it
         if attr == '_messenger':
             return object.__getattribute__(self,attr)

         #Return the value of the _messenger instance if its there. 
         elif hasattr(self._messenger,attr):
             return getattr(self._messenger,attr)

         #Otherwise return the instances own value
         else:
             if attr in self.__dict__:
                 val =  object.__getattribute__(self,attr)
                 #keep the messenger synchronized
                 setattr(self._messenger,attr,val)
                 return val
             else:
                 raise AttributeError()


     def __setattr__(self,attr,val):
         #set the messenger if necessary
         if attr == '_messenger':
             self.__dict__[attr] = val  
         #otherwise, set the attribute and sync the messenger
         else:
             setattr(self._messenger,attr,val)
             self.__dict__[attr] = val

class Messenger:
    def __init__(self):
        self.param1 = 1

class SubClassA(MessengerWrapper):
    def __init__(self,messenger):
        self._messenger = messenger
        self.paramA = 2

class SubClassB(MessengerWrapper):
    def __init__(self,messenger):
        self._messenger = messenger
        self.paramB = 3

    def function(self):
        total = self.param1 + self.paramB + self.subA.paramA
        self.paramA = total

messenger = Messenger()
A = SubClassA(messenger)
B = SubClassB(messenger)
messenger.subA = A
messenger.subB = B

B.function()

print messenger.paramA, B.paramA
#-> 6, 6 (as expected)
print A._messenger.paramA, A.paramA
#-> 6, 2 (I would expect 6, 6 since A.paramA should return A._messenger.paramA)

Jeg gjetter at dette avviket skyldes en manglende forståelse for når ting blir lagret ved henvisning vs. av verdi i Python, eller kanskje noen rare smutthull i getattr overstyring. Kanskje jeg kan legge til noen form for synkroniseringsfunksjonen for å sikre at alt forblir synkronisert opp, men det føles allerede ganske hackish og jeg vil tro at det er en renere løsning. Det endelige målet er å ha en budbringer klasse og underklasser som samhandler transparent med at messenger for å lage / lagre attributter og holde alt synkronisert.

Merk at selv om dette eksempelet ikke viser det, selve applikasjonen krever også at underklassene har tilgang til hverandres metoder (samt messenger metoder). Ikke sikker på om dette gjør noen forskjell eller ikke.

Noen ideer? Er jeg på rett spor eller skal jeg gjøre noe helt annet? Jeg så inn i metaklasser og dekoratører, men kunne ikke umiddelbart se om / hvordan de ville hjelpe meg.

Publisert på 29/05/2013 klokken 14:18
kilden bruker
På andre språk...                            


1 svar

stemmer
1

Har titt på forekomst attributter:

A.__dict__ {'paramA': 2, '_messenger': <__main__.Messenger instance at 0x100468cf8>}
A._messenger.__dict__ {'subA': <__main__.SubClassA instance at 0x100468d40>, 
                       'subB': <__main__.SubClassB instance at 0x100468d88>, 
                       'paramA': 6, 'param1': 1, 'paramB': 3}

Python alltid ser i forekomsten dict først. Den finner 'paramA'i A.__dict__. Hvis det ikke ville være der det ville gå opp til klassen og ville ringe __getattr__ fordi du tvinge den med __getattribute__.

Følgelig hindrer innstillingen inn i forekomsten dict ville endre virkemåten. Når du skriver self.paramA = totalat du kaller denne metoden:

 def __setattr__(self,attr,val):
     if attr == '_messenger':
         self.__dict__[attr] = val
     #otherwise, set the attribute and sync the messenger
     else:
         setattr(self._messenger,attr,val)
         # comment out the following line to get your 6
         self.__dict__[attr] = val

Den aller siste linjen self.__dict__[attr] = valsetter attributtet i forekomsten dict. Kommentar ut denne linjen, og du får resultatet du forventer. Hvis dette er fornuftig for problemet på hånden er et annet spørsmål om.

Svarte 29/05/2013 kl. 16:30
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more