我想我对Python中的模块命名空间有点困惑。 我和Byteplay玩过,这就是我尝试过的:
我构建了一个操作码列表,相当于:(byteplay的printcodelist) - >
0 LOAD_CONST 3
1 STORE_NAME a
2 LOAD_CONST None
3 RETURN_VALUE
然而,当我这样执行时:
exec mycode in t #t is {}
print 'a' in t #False , but I expected True
当我<{p>
import b
'a' in b.__dict__ #False
b.a #error
时也是如此
当我用 STORE_NAME
替换 STORE_GLOBAL
时,它可以工作。但是我认为STORE_NAME用于在当前本地命名空间中存储值。但是,顶层的本地命名空间与全局命名空间不同命名空间
例如locals() == globals()
如果仅使用它,则在主范围内为真。
基本上: 如果我用内置的编译函数编译“a = 3”,
dis.dis() and bytecode's Code.from_code(codeobject) show STORE_NAME。 HM
答案 0 :(得分:1)
我试图重现你的步骤,一切都对我很好。让我们一步一步看到这个过程。首先,代码创建。
我们在这里导入我们需要的所有内容:
from byteplay import Code, LOAD_CONST, STORE_NAME, RETURN_VALUE
让我们创建一个带有适当参数的操作码列表(元组列表,每个元组包含操作码作为第一个元素,参数作为第二个元素):
lst = [
(LOAD_CONST, 3),
(STORE_NAME, 'a'),
(LOAD_CONST, None),
(RETURN_VALUE, None)
]
好的,完成了。接下来,最负责的步骤是创建Code对象。它接收 10个参数。让我们来看看:
x = Code(
lst, # opcodes list (what we execute)
[], # outer scope variables (obviously, we don't have any here),
[], # arguments (nothing here),
False, # *args here? Nope
False, # **kwargs here? Nope
False, # !!!Important!!! DO WE CREATE NEW NAMESPACE? No! We use given!
'', # name ...
'', # filename ... who cares...
0, # first line number
'' # docstring
)
注意!如果代码创建的第6个参数设置为True,则在执行代码后,您将不会收到存储在locals中的'a'变量。这就是功能的运作方式。他们创建自己的命名空间(co_names),我们执行代码的命名空间不会使用'a'变量修补。
所以,让我们来吧!
nsloc = {} # locals to execute code with
nsglob = {} # globals to execute code with
# We could use one namespace for both but that doesn't matter
exec x.to_code() in nsglob, nsloc
print nsloc
而且,结果如预期:
{'a': 3}
希望有所帮助。