チケット #52 (new blog)
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で代入された値が残っていて使える、、、なんてことはないということ。
個人的には=は代入、という意識が強かったけれど、こういう挙動を見ていると、確かに代入という用語より束縛、と言う用語をつかう理由がなんとなくわかった気がする。
チケットの履歴
Note: チケットについてのヘルプは
TracTickets を参照
して下さい。