如何让一个对象在另一个对象的属性改变时调用一个方法?

2024-09-27 09:23:14 发布

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

我想建立一个系统,每当修改另一个对象的属性时,调用一个对象的方法,并将新值作为方法的参数。我怎样才能完成这样的事情?你知道吗

编辑:代码示例/澄清:

我的代码如下所示:

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的新值作为参数。有什么好办法吗?你知道吗


Tags: 对象方法keyselfinitvaluedefattributes
2条回答

一种方法是使用类似于Django使用ModelManager(例如model.objects)的manager样式属性:

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()调用,所以跟踪您的继承非常重要。我不知道你的应用程序是如何设置的,但是如果你使用多重继承,事情会变得很奇怪。你知道吗

如果你对哪些属性被更新很明确,并且你对那些属性有特殊的了解,你不需要知道什么时候某个对象的每个属性都发生了变化,那么你可能只需要通过属性来获得某种观察者模式。你知道吗

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属性而不是instance属性,这有其自身的优点和缺点。你知道吗

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原型-y,所以喜欢Python的人看起来像Python,可能会拿出他们的烹饪勺子,用它们来揍你。你知道吗

我想最终如果你想这样做,你只需要坚持装饰。属性访问器不会以一种不需要编写getter/setter就可以“挂接”的方式公开,因此您几乎肯定会想要属性和装饰器。你知道吗

相关问题 更多 >

    热门问题