4

我希望能够拦截函数内的变量赋值并执行自定义代码。我尝试创建一个自定义字典,如下所示:

class userdict(dict):
    def __setitem__(self, key, value):
        print 'run my code'
        dict.__setitem__(self, key, value)

如果我使用它作为全局字典来执行代码,那么我的自定义代码将在每个变量分配上运行。例如:

UserDict = userdict()
exec 'x = 1' in UserDict
#outputs 'run my code'

但是如果我的代码在函数内部,它就不起作用:

code = """
def foo():
    global x
    x = 1
"""
exec code in UserDict
UserDict['foo']()

在这种情况下,分配了“x”,但我的自定义代码没有运行。我假设在一个函数中,全局 dict 正在以某种方式被修改而不调用 setitem。这个对吗?有没有办法拦截函数内的变量赋值并执行自定义代码?

我想这样做是为了将函数中可用的某些对象与我程序中的其他对象同步。换句话说,当函数内部发生对某些变量的赋值时,该更改应该传播到我程序中的其他变量。

4

1 回答 1

3

问题可能是内置dict方法不会在 CPython 的子类方法中调用覆盖。Pypy,Jython 调用自定义__setitem__(),以便他们在设置时立即看到x

dis模块显示STORE_GLOBAL用于设置x

>>> def f():
...     global x
...     x = 1
...
...
>>> import dis
>>> dis.dis(f)
  4           0 LOAD_CONST               1 (1)
              3 STORE_GLOBAL             0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE

它被实现ceval.c为:

    TARGET(STORE_GLOBAL)
        w = GETITEM(names, oparg);
        v = POP();
        err = PyDict_SetItem(f->f_globals, w, v);
        Py_DECREF(v);
        if (err == 0) DISPATCH();
        break;

ifPyDict_SetItem()替换为PyObject_SetItem()then CPython 也可以工作,即__setitem__()调用 custom。

于 2012-11-07T06:31:05.410 回答