0

我想创建一个包含在其他几个类之间共享的信使类的结构。我想保持信使和子类之间的参数同步,并且我还希望子类能够通过信使相互访问。我目前已按如下方式实现它,但在同步方面存在一些问题:

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)

我猜测这种差异是由于缺乏对在 Python 中何时通过引用存储事物与按值存储事物的理解,或者可能是getattr覆盖中存在一些奇怪的漏洞。也许我可以添加某种同步功能来确保一切都保持同步,但它已经感觉很hackish,我认为有一个更清洁的解决方案。最终目标是拥有一个信使类和子类,它们与该信使透明地交互以创建/存储属性并保持一切同步。

注意,虽然这个例子没有展示出来,但实际的应用程序还要求子类可以访问彼此的方法(以及信使的方法)。不确定这是否有任何区别。

有任何想法吗?我是在正确的轨道上还是应该做一些完全不同的事情?我查看了元类和装饰器,但无法立即看到它们是否/如何帮助我。

4

1 回答 1

1

查看实例属性:

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 总是首先查看实例字典。它'paramA'A.__dict__. 如果它不在那里,它会去上课并打电话给你__getattr__ ,因为你用__getattribute__.

因此,阻止设置到实例字典中会改变行为。编写self.paramA = total时调用此方法:

 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

最后一行self.__dict__[attr] = val将属性放入实例字典中。注释掉这一行,你会得到你期望的输出。如果这对手头的问题有意义,那是一个不同的问题。

于 2013-05-29T16:30:39.697 回答