创建一个行为类似于任何变量但在更改/读取时具有回调的类

use*_*290 4 python class callback descriptor variable-assignment

我想创建一个行为python变量的类,但在更改/读取"变量"时调用一些回调函数.

换句话说,我希望能够如下使用该类:

x=myClass(change_callback, read_callback)
Run Code Online (Sandbox Code Playgroud)

将x定义为myclass的一个实例.构造函数(INIT)将2个函数作为参数:每次x更改时调用的函数,以及每次x"读取"时调用的函数

以下声明:

x=1
Run Code Online (Sandbox Code Playgroud)

将"保存"1并触发change_callback(1)可以执行任何操作的呼叫.

以下声明:

a=x
Run Code Online (Sandbox Code Playgroud)

将检索存储的值并调用read_callback()可能会更改存储的值并执行其他操作.

我希望这适用于任何类型,例如,以便能够编写如下内容:

x=[1 2 3] 哪会触发 change_callback([1 2 3])

x.append(4)会触发change_callback([1 2 3 4])(也可能是read_callback()之前的调用)

x={'a':1} 会触发 change_callback({'a':1})

print(x) 当然,会触发对read_callback()的调用...并返回最后存储的值进行打印.

这个想法是可以记录对变量的任何访问,或者无缝地生成其他计算.

我觉得这应该是可能的,但我并没有真正看到我的对象应该继承的内容......如果我必须将我限制为一种类型,例如列表,是否有任何方法可以重新定义所有赋值运算符(包括"one go"中的append()...等方法,保持原始行为(基类方法)并添加回调...

或者是否有更合适的方法(模块......)来实现相同的目标......?

提前致谢,

Ray*_*ger 8

对象不知道何时将它们分配给变量.写作x = a补充说,指向一个字典条目(或当地人条目)一个.在一个对象不会得到通知(不过,在CPython的,它的引用计数被递增).

获得通知的部分是分配对象的容器.在全局赋值的情况下,模块字典会更新.在实例变量更新的情况下a.b = x,有一个虚线查找和存储到实例字典.

您可以使这些容器在查找或存储上调用任意代码.Python的属性为新式类提供了这种功能.在EXECEVAL操作让你指定一个自定义字典,可以提供这种能力来定期分配.在这两种情况下,您都可以完全控制分配时发生的事情.

简介:查找和存储行为可通过赋值的目标而不是分配的对象来控制.

示例:

from collections import namedtuple

CallbackVar = namedtuple('CallbackVar', ['change_callback', 'read_callback'])

class CallbackDict(dict):
    'Variant of dict that does callbacks for instances of CallbackVar'
    def __getitem__(self, key):
        value = dict.__getitem__(self, key)
        if isinstance(value, CallbackVar):
            return value.read_callback(key)
    def __setitem__(self, key, value):
        try:
            realvalue = dict.__getitem__(self, key)
            if isinstance(realvalue, CallbackVar):
                return realvalue.change_callback(key, value)
        except KeyError:
            pass
        return dict.__setitem__(self, key, value)

stmts = '''
x = CallbackVar(setter, getter)     # Attach getter() and setter() to "x"
x = 1                               # Invoke the setter()
x                                   # Invoke the getter()
'''

def getter(key):
    print 'Getting', key
    return 42

def setter(key, value):
    print 'Setting', key, 'to', value

exec stmts in globals(), CallbackDict()
Run Code Online (Sandbox Code Playgroud)