exec()方法中自定义名称空间的子类化python字典 [英] subclassed python dictionary for custom namespace in exec() method
问题描述
我正在尝试将字典子类化以便在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屋!