主要范围内的STORE_NAME和STORE_GLOBAL等效吗?

时间:2011-12-09 21:05:08

标签: python module scope bytecode

我想我对Python中的模块命名空间有点困惑。 我和Byteplay玩过,这就是我尝试过的:

  1. 我构建了一个操作码列表,相当于:(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

1 个答案:

答案 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}

希望有所帮助。