如何为函数的全局字典覆盖__setitem__? [英] How to override __setitem__ for a function's globals dict?

查看:85
本文介绍了如何为函数的全局字典覆盖__setitem__?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够拦截函数中的变量分配并执行自定义代码.我尝试过如下创建自定义字典:

I want to be able to intercept variable assignments within a function and execute custom code. I have tried creating a custom dict as follows:

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

如果我使用此代码作为全局命令执行代码,则我的自定义代码将在每个变量赋值上运行.例如:

If I exec code using this as the global dict, then my custom code will run on each variable assignment. e.g.:

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

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

But if my code is inside a function, it doesn't work:

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

在这种情况下,已分配'x',但是我的自定义代码无法运行.我假设在一个函数中,全局dict会以某种方式修改而无需调用setitem.这样对吗?有没有办法拦截函数中的变量分配并执行自定义代码?

In this case, 'x' is assigned, but my custom code does not run. I assume that within a function, the global dict is being modified somehow without calling setitem. Is this correct? Is there a way to intercept variable assignments within a function and execute custom code?

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

I want to do this in order to synchronize certain objects available inside a function with other objects in my program. In order words, when the an assignment to certain variables occurs inside the function, that change should propagate to other variables in my program.

推荐答案

问题可能是内置的dict方法未调用CPython中子类方法中的重写方法. Pypy,Jython调用了自定义__setitem__(),因此当设置x时,他们会立即看到.

The issue might be that builtin dict methods don't call overridden in subclasses methods in CPython. Pypy, Jython call custom __setitem__() so they see immediately when x is set.

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;

如果将PyDict_SetItem()替换为PyObject_SetItem(),则CPython也可以工作,即调用自定义__setitem__().

if PyDict_SetItem() is replaced with PyObject_SetItem() then CPython also works i.e., custom __setitem__() is called.

这篇关于如何为函数的全局字典覆盖__setitem__?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆