我想创建一个结构,其中包含一个在其他几个类之间共享的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的方法)。不知道这是否有什么不同。你知道吗
有什么想法吗?我是在正确的轨道上还是应该做一些完全不同的事情?我查看了元类和装饰器,但无法立即看到它们是否/如何帮助我。你知道吗
查看实例属性:
Python总是首先查看实例dict。它在
A.__dict__
中找到'paramA'
。 如果它不在那里,它将转到类并调用您的__getattr__
因为你用__getattribute__
强迫它。你知道吗因此,阻止实例dict中的设置将改变行为。 编写
self.paramA = total
时,调用此方法:最后一行
self.__dict__[attr] = val
将属性放入实例dict中。 注释掉这一行,就得到了预期的输出。如果这对手头的问题有意义的话,那就另当别论了。你知道吗相关问题 更多 >
编程相关推荐