localsに関して誤解していた件
Python2.6とかで
>>> def foo(): ... locals()["hoge"] = 1 ... print hoge ... >>> foo() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in foo NameError: global name 'hoge' is not defined
こうなるわけで、これはローカルの名前空間が最適化の関係で書き換え不可になっていてlocals()が返すのはそのコピーを辞書ライクにしたものだと思ってたんだ。
でもこれってコンパイル時にhogeが存在しないからLOAD_GLOBALになっているってだけで
>>> import dis >>> dis.dis(foo) 2 0 LOAD_CONST 1 (1) 3 LOAD_GLOBAL 0 (locals) 6 CALL_FUNCTION 0 9 LOAD_CONST 2 ('hoge') 12 STORE_SUBSCR 3 13 LOAD_GLOBAL 1 (hoge) 16 PRINT_ITEM 17 PRINT_NEWLINE 18 LOAD_CONST 0 (None) 21 RETURN_VALUE
こうすればちゃんと書き変わっているのが参照できる。
>>> def foo(): ... locals()["hoge"] = 1 ... print eval("hoge") ... >>> foo() 1
「これはローカルの名前空間が最適化の関係で書き換え不可になっていてlocals()が返すのはそのコピーを辞書ライクにしたものだと思ってたんだ。」
これが正解で、evalできるのはlocals()を書き換えたときの動作が未定義だから実装のためにたまたまevalできただけ。
by id:methane