exec()方法中自定义名称空间的子类化python字典 [英] subclassed python dictionary for custom namespace in exec() method

查看:123
本文介绍了exec()方法中自定义名称空间的子类化python字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将字典子类化以便在exec方法中使用. 最终,我希望本地函数具有自定义名称范围行为.

I am trying to subclass a dictionary for use in an exec method. Ultimately, I would like the local function to have a custom name scoping behaviour.

在下面的代码中,功能b()实际上确实具有正确的globals()字典可用,但是在解析z时无法搜索它.

In the code below, function b() does in fact have the correct globals() dictionary available to it, however it fails to search it when resolving z.

功能b()首先不搜索locals(),然后搜索globals()吗?

Does function b() first not search locals() then globals() ?

非常令人困惑. 任何帮助表示赞赏.

Very puzzling. Any help appreciated.

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

推荐答案

在python 3.3之前,您不能使用自定义的dict子类作为exec语句的globals值.执行已编译代码的基础C代码直接访问基础C结构,而忽略了您可能已实现的任何自定义钩子.

Before python 3.3, you cannot use a custom dict subclass for the globals value of an exec statement. The underlying C code that executes the compiled code accesses the underlying C structures directly, ignoring any custom hooks you may have implemented.

换句话说,当代码执行LOAD_GLOBAL操作时(如函数b中的z一样),C字节码评估循环使用以下命令访问当前帧中的globals结构. C API ,绕过所有python覆盖.

In other words, when the code does a LOAD_GLOBAL operation (as is the case with z in your function b), the C bytecode evaluation loop accesses the globals structure in the current frame using the C API, bypassing any python overrides.

exec()函数文档中对此进行了记录:

This is documented in the exec() function documentation as:

如果仅提供 globals ,则它必须是字典,该字典将用于全局变量和局部变量.如果给出了 globals locals ,它们分别用于全局变量和局部变量.如果提供的话, locals 可以是任何映射对象.

If only globals is provided, it must be a dictionary, which will be used for both the global and the local variables. If globals and locals are given, they are used for the global and local variables, respectively. If provided, locals can be any mapping object.

此限制已在Python 3.3中放宽,请参见 issue 14385 .该文档尚未更新,但是字节码评估循环已更新为在回退到C API访问之前测试自定义映射.如果使用自定义映射,则使用PyObject_GetItem函数,它将在自定义类上调用__getitem__.

This restriction has been loosened in Python 3.3, see issue 14385. The documentation hasn't been updated yet, but the bytecode evaluation loop has been updated to test for custom mappings before falling back to the C API access. If a custom mapping is used, the PyObject_GetItem function is used, which will call __getitem__ on custom classes.

这篇关于exec()方法中自定义名称空间的子类化python字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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