読者です 読者をやめる 読者になる 読者になる

locals()["x"] = 1は意味が無い

locals()["x"] = 1

locals()を変更すると変数を無理矢理定義できる!
というのをどこかで見た記憶がありますが、それはウソです。


ドキュメントを見てもlocals()の変更は意味がありません。

locals()
現在のローカルシンボルテーブルを表す辞書を更新して返します。 警告: この辞書の内容は変更してはいけません; 値を変更しても、インタプリタが使うローカル変数の値には影響しません。

このコードを実行してみると分かります。

from __future__ import division, print_function, unicode_literals

# globals() はいじれる
globals()["x0"] = 0 
print(x0) # => 0

# locals() もいじれる
locals()["x1"] = 1
print(x1) # => 1

def spam():
    # globals() はいじれる
    globals()["x2"] = 2
    print(x2) # => 0
    
    # locals() はいじれない
    locals()["x3"] = 3
    print(x3) # => NameErrorが発生
    
spam()

globals()はいじれるようですが、関数の中のlocals()はいじれません。
グローバルスコープではlocals()もいじれていますが、それはglobals()とlocals()がグローバルスコープでは同じ辞書だからです。

from __future__ import division, print_function, unicode_literals

print(locals() is globals()) # => True
def spam():
    print(locals() is globals()) # => False
spam()


しかしながら、ローカル変数を好き勝手に定義したい事はたまによくあります。
テンプレートエンジンを作る時とか。

そんなときにはexec文を使えば良いでしょう。

from __future__ import division, print_function, unicode_literals

def spam():
    adict = {"x": 1, "y":2, "z":3}
    for k, v in adict.items():
        exec "{0} = v".format(k)
    
    print(x, y, z) # => 1 2 3
spam()