我有一个具有多个属性的可变对象(我们称之为 mutable
)。该对象本身是 Foo
类中的一个属性。 Foo
是用户定义的,而 mutable
不是,因此不能更改。
每当有人试图在 mutable
中设置属性时,我都需要进行计算。我面临的问题是,使用 mutable
的属性仅在设置了 mutable
本身而不是其属性时才有效。我已经设法解决了这个问题,但使用的东西似乎比合理的 Python 代码更像是 hack。
class Mutable(object): # Example class.
def __init__(self):
self.attr0 = 0
self.attr1 = 1
def __repr__(self):
return str(self.__dict__)[1:-1]
class Foo(object):
def __init__(self):
self._mutable = Mutable()
@property
def mutable(self):
print('mutable was read')
return self._mutable
@mutable.setter
def mutable(self, attr_value_pair):
attribute, value = attr_value_pair
setattr(self._mutable, attribute, value)
print('mutable.' + attribute, 'was set to', value)
bar = Foo()
print(bar.mutable) # 'mutable was read'
bar.mutable = ('attr0', 5) # 'mutable.attr0 was set to 5'
bar.mutable = ('attr1', 10) # 'mutable.attr1 was set to 10'
print(bar.mutable) # 'mutable was read'
# This is what I want to do but it only calls the getter.
bar.mutable.attr0 = 0 # 'mutable was read'
bar.mutable.attr1 = 1 # 'mutable was read'
有什么方法可以识别 mutable
中的属性何时以更 Pythonic 的方式设置?
编辑: 澄清一下:Foo
需要知道 mutable
何时更改,因为 Foo
具有依赖于可变
。 Mutable
可以被继承。
最佳答案
最简单干净的解决方案是子类化 mutable
- 但我认为这不是一个选项。
最简单的“quick&dirty”解决方案是使用 monkeypatch mutable
- 但这实际上是最后的解决方案,从长远来看是在寻找麻烦。
因此,如果您不能将 mutable
子类化,也不能控制它的实例化,并且不想对其进行 monkeypatch,那么您只能使用 proxy
模式。
编辑:哦,是的,因为它是 Foo
需要得到关于 self._mutable
更改的通知,你必须将它与观察者模式结合起来(这里是非常有限的形式):
class Mutable(object): # Example class.
def __init__(self):
self.attr0 = 0
self.attr1 = 1
def __repr__(self):
return str(self.__dict__)[1:-1]
class MutableProxy(object):
def __init__(self, mutable, owner):
self._mutable = mutable
self._owner = owner
@property
def attr0(self):
return self._mutable.attr0
@attr0.setter
def attr0(self, value):
self._mutable.attr0 = value
self._owner.notify("set", "attr0", value)
@property
def attr1(self):
return self._mutable.attr1
@attr1.setter
def attr1(self, value):
self._mutable.attr1 = value
self._owner.notify("attr1", value)
def __repr__(self):
return "<MutableProxy for {}>".format(repr(self._mutable))
class Foo(object):
def __init__(self):
self.mutable = Mutable()
@property
def mutable(self):
#print('mutable was read')
return self._mutable
@mutable.setter
def mutable(self, value):
self._mutable = MutableProxy(value, self)
def notify(self, attrname, value):
print('self._mutable.{} was set to {}'.format(attrname, value))
注意:我没有在 MutableProxy.__init__
中添加任何类型检查,这取决于你真正的 mutable
实际上是什么你可能想要确保你至少得到一些东西兼容...
NB2:我在 ProxyMutable
上使用了显式属性,因为它使事情更清晰,但您可能想使用 __getattr__
/__setattr__
Hook (至少对于您不需要控制访问的 mutable
属性)。
NB3:我们现在在 Foo
和 MutableProxy
之间有一个循环引用。 Python normalluy 知道如何摆脱循环引用,但如果它碰巧仍然是您的具体用例的问题,您可能希望将 MutableProxy._owner
设置为 weak reference相反。
现在困扰我的问题是:为什么要公开 mutable
?完全隐藏它并仅通过 Foo
方法或属性提供对其属性的访问将使代码更简单(并且更容易推理并且不太可能产生意外副作用)。
关于python - 如何识别属性的属性何时被设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41330968/