在python中包装和同步messenger类

2024-04-27 03:04:53 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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重写中存在一些奇怪的漏洞。也许我可以添加一些同步功能,以确保一切保持同步,但它已经感觉相当黑客,我认为有一个更干净的解决方案。最终目标是拥有一个messenger类和子类,这些类与该messenger透明地交互,以创建/存储属性并保持所有内容的同步。你知道吗

请注意,尽管本例没有显示,但实际应用程序还要求子类可以访问彼此的方法(以及messenger的方法)。不知道这是否有什么不同。你知道吗

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


Tags: theselfreturnifdefval子类messenger
1条回答
网友
1楼 · 发布于 2024-04-27 03:04:53

查看实例属性:

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总是首先查看实例dict。它在A.__dict__中找到'paramA'。 如果它不在那里,它将转到类并调用您的__getattr__ 因为你用__getattribute__强迫它。你知道吗

因此,阻止实例dict中的设置将改变行为。 编写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将属性放入实例dict中。 注释掉这一行,就得到了预期的输出。如果这对手头的问题有意义的话,那就另当别论了。你知道吗

相关问题 更多 >