python中的变量更改回调

时间:2018-08-16 20:59:02

标签: python events concurrency

我已经搜索了周围,但是没有找到类似的东西。假设我有很多线程,它们不断读取和更新整数变量x。我想要一个x超过一定幅度(例如500)的回调来运行回调。

如何在不给系统带来沉重负担的情况下完成此工作,例如使线程具有while true并检查变量是否已更改?性能至关重要。但是道德也是如此。

用普通代码是这样的:

x = 10
def runMe():
    print('Its greater than 500!!') 

def whenToRun():
    return x >= 500

triggers.event(runMe, whenToRun)

2 个答案:

答案 0 :(得分:1)

您想要一个函数(一个“ setter” ),该函数在变量值更改时被调用。做到这一点的一个好方法是定义一个@property。它的行为类似于变量,但具有 getter 函数和 setter 函数。

然后,在设置器中,调用所需的任何回调,这些回调将对更改做出反应。

这应该可以解决问题:

class ObjectHoldingTheValue:
    def __init__(self, initial_value=0):
        self._value = initial_value
        self._callbacks = []

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, new_value):
        old_value = self._value
        self._value = new_value
        self._notify_observers(old_value, new_value)

    def _notify_observers(self, old_value, new_value):
        for callback in self._callbacks:
            callback(old_value, new_value)

    def register_callback(self, callback):
        self._callbacks.append(callback)

然后,您可以执行以下操作:

def print_if_change_greater_than_500(old_value, new_value):
    if abs(old_value - new_value) > 500:
        print(f'The value changed by more than 500 (from {old_value} to {new_value})')

holder = ObjectHoldingTheValue()
holder.register_callback(print_if_change_greater_than_500)
holder.value = 7    # nothing is printed
holder.value = 70   # nothing is printed
holder.value = 700  # a message is printed

答案 1 :(得分:0)

如果x是某个对象的属性,而不是全局变量,那么这很简单:添加一个__setattr__方法:

class MyType:
    def __setattr__(self, name, value):
        if name == 'x':
            self.x_callback(value)
        super().__setattr__(name, value)

很显然,有一些方法可以使它更灵活:

  • 添加一种动态注册条件的方法,而不仅仅是始终调用x_callback
  • 为它添加一个mixin类,该类可以附加到任何其他类上,让您register(name, callback)随心所欲。
  • 合并以上内容,以便可以register(name, condition, callback)
  • self.x_callback(oldval=self.x, newval=value),以便回调程序可以看到旧值和新值。
  • if self.x_callback(value):,以便回调可以接受或拒绝更改。
  • value = self.x_callback(value),以便回调可以覆盖更改。