子类蟒字典中EXEC自定义命名空间()方法(subclassed python dictionary

2019-06-27 13:44发布

我试图子类的字典用在exec方法。 最后,我想当地的功能,有一个自定义名称作用域的行为。

在下面的代码,函数b()事实上确实有正确的globals()的字典提供给它,但它未能解决时要搜索它z

是否函数b()先不要搜索locals()globals()

十分不解。 任何帮助表示赞赏。

t = '''
def b():
#   return (globals()['z']) #works
    return z #fails

b()
'''

class MyDict(dict):
    def __init__(self, g):
        dict.__init__(self)
        self.my_g = g


    def __getitem__(self, key):
        print("GET ", key)
        try:
            val = dict.__getitem__(self, key)
        except:
            print("GET exception1")
            val = self.my_g[key]
        return val


g = {'z':123}

md = MyDict(g)

#fails to find z
exec(t, md, md)

#works
#exec(t, g, g)

产量

GET  b
Traceback (most recent call last):
  File "/project1/text12", line 31, in <module>
  File "<string>", line 6, in <module>
  File "<string>", line 4, in b
NameError: global name 'z' is not defined

Answer 1:

蟒蛇3.3之前,您不能使用自定义dict的子类globals的exec语句的值。 执行编译后的代码底层的C代码直接访问底层的C结构,忽略你可能已经实现了任何自定义挂钩。

换句话说,当代码做了LOAD_GLOBAL操作(如与壳体z在函数b )中,C字节码评估环路访问globals中使用当前帧结构C API ,绕过任何蟒覆盖。

这是记录在在exec()函数文档为:

如果只提供全局变量 ,它必须是一个字典,这将被用于全球和局部变量。 如果全局当地人给出,它们分别用于全局和局部变量。 如果提供的话, 当地人可以是任何映射对象。

这种限制已经在Python 3.3被松开,见问题14385 。 文档尚未更新,但字节码估价循环已经更新回落至C API访问之前测试自定义映射。 如果使用自定义的映射, PyObject_GetItem功能时,它会调用__getitem__定制类。



文章来源: subclassed python dictionary for custom namespace in exec() method