python中变量变化的回调

Vla*_*tra 6 python concurrency events

我四处搜索,但没有找到类似的东西。假设我有一大群线程,它们不断读取和更新整数变量x。我想要一个回调,当x变化超过一定的幅度时,比如 500,来运行回调。

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

在普通代码中将是这样的:

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

def whenToRun():
    return x >= 500

triggers.event(runMe, whenToRun)
Run Code Online (Sandbox Code Playgroud)

zvo*_*one 13

您想要一个函数(一个 “setter”),每当变量的值发生变化时都会调用它。一个很好的方法是定义一个@property. 它的行为就像一个变量,但会有一个getter函数和一个setter函数。

然后,在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)
Run Code Online (Sandbox Code Playgroud)

然后,你可以这样做:

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
Run Code Online (Sandbox Code Playgroud)


aba*_*ert 5

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

class MyType:
    def __setattr__(self, name, value):
        if name == 'x':
            self.x_callback(value)
        super().__setattr__(name, value)
Run Code Online (Sandbox Code Playgroud)

显然,有一些方法可以使其更加灵活:

  • 添加一种动态注册条件的方法,而不是总是调用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)因此回调可以覆盖更改。