チケット #52 (new blog)

登録: 10 か月

最終更新: 5 か月

pythonのクロージャで遭遇したスコープ問題

報告者: mtamaki 担当者: mtamaki
優先度: major マイルストーン:
コンポーネント: blog バージョン:
キーワード: 関係者:

説明 (最終更新者: mtamaki) (diff)

pythonの変数のスコープの仕様について自分の理解が浅かったことを発見したので備忘としてメモ

以下のコードは#2の場所でUnboundLocalErrorとなる。

def a():
        b = 1   #1
        print b
        def c():
                print b #2
                b = 2   #3
        c()
a()

これは、代入を行われた変数のスコープは、行われたブロック全体に対して有効というpythonの仕様によるもの。(Ref: 4.1 名前づけと束縛 (naming and binding))

まず、このコードは#3の行がコメントアウトされていれば問題なく動く。 しかし、#3の行があると、bへの代入が行われるため、関数cにおけるbは#3のbを指すこととなる。 つまり、#2におけるbは#3のbであり、#1のbではなくなる。 そして、#2の行が実行されているときには#3のbはまだ初期化されていないので、UnboundLocalErrorとなる。

つまり、#3で代入されるまでは#1で代入された値が残っていて使える、、、なんてことはないということ。

個人的には=は代入、という意識が強かったけれど、こういう挙動を見ていると、確かに代入という用語より束縛、と言う用語をつかう理由がなんとなくわかった気がする。

チケットの履歴

更新者: mtamaki (5 か月 前)

  • 説明 が変更されました (diff)

更新者: mtamaki (5 か月 前)

  • 説明 が変更されました (diff)
Note: チケットについてのヘルプは TracTickets を参照 して下さい。