4

関数内で変数の割り当てを傍受し、カスタム コードを実行できるようにしたいと考えています。次のようにカスタムdictを作成しようとしました:

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

これをグローバル dict として使用してコードを実行すると、カスタム コードが変数の割り当てごとに実行されます。例えば:

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」が割り当てられていますが、カスタム コードは実行されません。関数内で、 setitem を呼び出さずにグローバル dict が何らかの形で変更されていると仮定します。これは正しいです?関数内で変数の割り当てをインターセプトしてカスタム コードを実行する方法はありますか?

関数内で使用可能な特定のオブジェクトをプログラム内の他のオブジェクトと同期するために、これを実行したいと考えています。つまり、関数内で特定の変数への割り当てが発生すると、その変更はプログラム内の他の変数に伝播するはずです。

4

1 に答える 1

3

問題は、組み込みdictメソッドが CPython のサブクラス メソッドでオーバーライドされたメソッドを呼び出さないことである可能性があります。Pypy、Jython は custom を呼び出し__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;

ifを thenPyDict_SetItem()に置き換えるとPyObject_SetItem()、CPython も機能します。つまり、custom__setitem__()が呼び出されます。

于 2012-11-07T06:31:05.410 に答える