STORE_NAME и STORE_GLOBAL эквивалентны в основной области? - PullRequest
3 голосов
/ 10 декабря 2011

Думаю, я немного запутался в пространстве имен модулей в Python. Я играл с Byteplay, и вот что я попробовал:

  1. Я создал список кодов операций, эквивалентный: (список кодов печати byteplay) ->

    
    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
    

    то же самое происходит, когда я

    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 Ответ

1 голос
/ 16 августа 2012

Я пытался воспроизвести ваши шаги, и у меня все работало нормально. Давайте посмотрим на процесс шаг за шагом. Прежде всего, создание кода.

Здесь мы импортируем все, что нам нужно:

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, вы не получите переменную '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}

Надеюсь, это помогло.

...