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

查看:29
本文介绍了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 之前,您不能globals 使用自定义 dict 子类 exec 语句的值.执行编译代码的底层 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字节码评估循环使用 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()功能文档 as:

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

如果只提供了globals,它必须是一个字典,它将用于全局和局部变量.如果给出了 globalslocals,则它们分别用于全局变量和局部变量.如果提供,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天全站免登陆