我有一个可变对象(我们称之为mutable),它有多个属性。这个对象本身就是类Foo中的一个属性。Foo是用户定义的,而mutable不是,因此不能更改。每当有人试图在mutable中设置属性时,我就需要进行计算。我面临的问题是,使用mutable的属性仅在设置了mutable本身而不是其属性时才起作用。我已经成功地解决了这个问题,但是这看起来比合理的python代码更像是一个黑客。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需要知道Foo何时更改,因为mutable具有依赖于Foo的属性。mutable可以继承。 最佳答案 修订过的基本上,我同意Alessandro的 >,也就是说,您应该使用一些重要的差异来扩展 >类。一种是,如果它是从基类派生的,则不需要它还包含基类的单独(未使用的)实例。我错过了这个在我之前版本的答案。更重要的是,它支持用户提供的回调函数,当其一个属性被读取或写入时,它将被调用。这允许将通知发送回contain类-Mutable中的方法,在这种情况下,我认为它们的更改确实需要处理。注意:这并不一定意味着您可以删除Foo属性Foo。如果您想支持已经实现的元组赋值操作,那么仍然需要它,该操作允许像:mutable这样的语句设置bar.mutable = ('attr0', 5)的mutable属性。如果没有属性,您就需要编写:相反的(可能更清楚)。class Mutable(object): # Example class (unchangeable). def __init__(self): self.attr0 = 0 self.attr1 = 1 def __repr__(self): return str(self.__dict__)[1:-1]class MonitoredMutable(Mutable): _get_callback = _set_callback = lambda *_: None # no-op placeholders def __init__(self, get_callback, set_callback): # use superclass to avoid infinite recursion when setting attributes super_delegate = super(MonitoredMutable, self) super_delegate.__init__() super_delegate.__setattr__('_get_callback', get_callback) super_delegate.__setattr__('_set_callback', set_callback) def __setattr__(self, name, value): super(MonitoredMutable, self).__setattr__(name, value) self._set_callback(name, value) # write notification def __getattr__(self, name): self._get_callback(name) # read notification return super(MonitoredMutable, self).__getattr__(name, value) def __repr__(self): # optional # override to only display the public attributes of the instance public_attrs = {k:v for k,v in self.__dict__.items() if not k.startswith('_')} # assuming single inheritance (only one base class) base_classname = self.__class__.__bases__[0].__name__ return base_classname + ': ' + (str(public_attrs)[1:-1] if public_attrs else 'No pub attributes')class Foo(object): def __init__(self): self._mutable = MonitoredMutable(self._get_callback, self._set_callback) def _get_callback(self, name): print('mutable.' + name + ' was read') def _set_callback(self, name, value): print('mutable.' + name, 'was set to', value) @property def mutable(self): return self._mutable @mutable.setter def mutable(self, attr_value_pair): attribute, value = attr_value_pair setattr(self._mutable, attribute, value)bar = Foo()print(bar.mutable) # -> Mutable: 'attr0': 0, 'attr1': 1bar.mutable = ('attr0', 5) # -> mutable.attr0 was set to 5bar.mutable = ('attr1', 10) # -> mutable.attr1 was set to 10print(bar.mutable) # -> Mutable: 'attr0': 5, 'attr1': 10# These now workbar.mutable.attr0 = 1 # -> mutable.attr0 was set to 1bar.mutable.attr1 = 0 # -> mutable.attr1 was set to 0print(bar.mutable) # -> Mutable: 'attr0': 1, 'attr1': 0
09-25 21:53