スコープ判定とグローバル変数

pythonでグローバルな定義をしたいなー、と思ってちょっと調べてみたら、ちょっと面倒、というか不安になる仕組みになっていたのでメモしておく。
以下の内容は、ちょっと前に購入していた参考書「初めてのPython(第2版)」に分かりやすく記載されており、その確認と自分なりの補足メモです。参考になるのは、p.286の「変数がローカルスコープに属するかどうかはスタティックに決定される」という項目です。

関数の外の変数の参照

1.変数(X)が関数の外で定義されている
2.変数(X)が関数内で参照されている
3.関数内で変数(X)への代入処理が行われていない
以上の条件の場合、関数内で参照される変数は関数外の変数となる。

確認コード
X = 99
def testf():
  if X == 99:
    print "OK"
  else:
    print "NG:",X

testf()
print X

以上のコードを実行すると以下のように出力されます。

OK
99

関数の外の変数と同名の変数への代入

1.変数(X)が関数の外で定義されている
2.変数(X)が関数内で参照されている
3.関数内で変数(X)への代入処理が行われている
以上の条件の場合、関数内で参照される変数は関数内の変数となる。

確認コード
X = 99
def testf():
  X=10  # <= この行を追加.
  if X == 99:
    print "OK"
  else:
    print "NG:",X

testf()
print X

以上のコードを実行すると以下のようになります。

NG: 10
99

という出力がなされます.
また、この参照先の処理はスタティックに処理されるので、以下のコードはエラーになります。

X = 99
def testf():
  if X == 99:
    print "OK"
  else:
    print "NG:",X
  X=10  # <= 参照より後で変数へ値を代入.

testf()
print X

自分の環境では、"UnboundLocalError: local variable 'X' referenced before assignment"というエラーが吐かれます。

テスト環境

参考書

初めてのPython 第2版

初めてのPython 第2版