Je souhaite créer une structure avec une classe messenger partagée entre plusieurs autres classes. Je veux garder les paramètres synchronisés entre le messager et les sous-classes, et je veux aussi que les sous-classes puissent accéder les unes aux autres via le messager. J'ai actuellement mis en œuvre comme suit, mais je rencontre quelques problèmes avec la synchronisation:Habillage et synchronisation de classe messenger en python
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)
Je devine que ce écart résulte d'un manque de compréhension quand les choses sont stockées par référence par rapport à la valeur en Python, ou peut-être une échappatoire étrange dans le getattr override. Peut-être que je pourrais ajouter une sorte de fonction de synchronisation pour que tout reste synchronisé, mais il me semble déjà assez hackish et je pense qu'il y a une solution plus propre. L'objectif final est d'avoir une classe de messagers et des sous-classes qui interagissent de manière transparente avec ce messager pour créer/stocker des attributs et tout synchroniser.
Notez que bien que cet exemple ne le montre pas, l'application réelle requiert également que les sous-classes aient accès aux méthodes de l'autre (ainsi qu'aux méthodes du messager). Je ne sais pas si cela fait une différence ou non.
Des idées? Suis-je sur la bonne voie ou devrais-je faire quelque chose de totalement différent? J'ai regardé dans les métaclasses et les décorateurs, mais je n'ai pas pu voir immédiatement si/comment ils m'aideraient.
Très belle réponse. Je n'ai pas réalisé que python a vérifié '__dict__' avant d'appeler' __getattribute__'. Je peux certainement utiliser cette connaissance dans mon application. –