問題描述
我正在嘗試對字典進行子類化以在 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 使用自定義
exec 語句的值.執行編譯代碼的底層 C 代碼直接訪問底層 C 結構,忽略您可能已經實現的任何自定義掛鉤.dict
子類
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()
功能文檔 as:
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 字典的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!