我想建立一个系统,只要修改了不同对象的属性,就会调用一个对象的方法,并将新值作为方法的参数。我怎么能做到这样的事情?
编辑:代码示例/澄清:
我的代码看起来像这样:
class SharedAttribute(object): #I use this as a container class to share attributes between multiple objects
def __init__(self, value):
self.value = value
class BaseObject(object):
def __init__(self, **shared_attributes:
for (key, value) in shared_attributes:
if isinstance(value, SharedAttribute):
setattr(self, key, value)
else:
setattr(self, key, SharedAttribute(value))
class MyObject(BaseObject):
def __init__(self, value1, value2):
BaseObject.__init__(self, value1, value2)
def on_value_changed(self, new_value):
#Do something here
def incrementValue(self):
self.value1.value += 1
然后它将被实现为:
a = MyObject(value1 = 1)
b = MyObject(value1 = MyObject.value1) #a and b are storing references to the same attribute, so when one changes it, it's changed for the other one too.
我想设置它,所以如果我打电话给a.incrementValue()
,我会调用b.on_value_changed
,并以SharedAttribute
的新值作为参数。有没有办法做到这一点?
答案 0 :(得分:0)
一种方法是使用类似于Django使用ModelManager
' s(model.objects
的方式)的经理风格属性:
class Foo(object):
def method_to_call(self, new_val):
print('Hello from manager. Doing stuff with {}'.format(new_val))
class Bar(object):
manager = Foo()
def __init__(self, your_attr):
self.your_attr = your_attr
def __setattr__(self, key, val):
if key == 'your_attr':
self.manager.method_to_call(val)
super(Bar, self).__setattr__(key, val)
使用它:
>>> bar = Bar('some value')
Hello from manager. Doing stuff with some value
>>> bar.your_attr = 'A new value'
Hello from manager. Doing stuff with A new value
如果您想使用Foo
的特定实例来管理Bar
的特定实例,则可以修改__init__()
以获取Foo
的实例并使用它。由于我们在此处进行super()
调用,因此跟踪您的继承非常重要。我不知道你的应用是如何设置的,但如果你使用多重继承,事情可能会变得奇怪。
答案 1 :(得分:0)
如果您具体了解哪些属性正在更新,并且您对这些属性有特殊了解,那么每当某些对象的每个属性发生变化时,您都不需要知道 - 然后你可能只想通过属性获得某种观察者模式。
class A(object):
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
whatever_else_you_wanted_to_happen()
否则,如果你试图获得泛型(你可能不想要),那么你最终会包装一个类属性而不是一个实例属性,这有其自身的优点和缺点。
class B(object):
pass
def wrapper(objmethod):
def _inner(*args, **kwargs)
some_other_thing_you_wanted_to_happen()
return objmethod(*args, **kwargs)
return _inner
B.__setattr__ = wrapper(B.__setattr__)
这真的是一种JavaScript-y原型,但是那些像Python一样看起来像Python的人可能会把他们的烹饪勺子弄出来并用它们来打击你。
我认为,如果你想这样做,你会想要坚持装饰者。属性访问器不会以一种你可以“挂钩”而不编写getter / setter的方式公开,因此你几乎肯定会想要属性和装饰器。