2014/02/11

Pythonのスコープ その3

その 1その 2 に引き続き Python のスコープについて見ていきます。

みっつめのポイントは「スコープ内で使われる名前はスコープの先頭で作られる」というものです。

スコープ内で使われる名前はスコープの先頭で作られる


これは文章のとおりそのままなのですが、ことばだけでは説明しづらいので例をご覧ください。

C = 10

def myfunc1():
    print C

def myfunc2():
    print C
    if False:
        C = 100

myfunc1() # => 10
myfunc2()
# => UnboundLocalError: local variable 'C' referenced before assignment

ここで myfunc1() の呼び出しは問題なく動作しますが、 myfunc2() の呼び出しではエラーが上がります。

2 つの関数の違いとしては、 myfunc1() では単純に変数 C が参照されていますが、 myfunc2() の方では C が参照された後に条件付きで C が定義されている、という点が異なります。

ポイントは、 myfunc2() の中の if 文の評価結果は False なので実際には C = 100 の行には処理は到達しないという点です。

エラーの意味は「代入の前に C という名前を参照していますよね、それはできません」ということなのですが、こういうエラーが上がるということはつまり、「 myfunc2() の中の print C の行のところですでに C という名前が確保されており、グローバル空間の C への参照は失われている」ということを表します。

Python ではこのように、特定のスコープの中で定義された「名前」は巻き上げられ、スコープの先頭で確保される形になっているようです。

以上です。

ちなみに、 Python の場合にこの用語を使うかはわかりませんが、この「巻き上げ」処理のことを英語では「 hoisting 」(ホイスティング)と呼ぶそうです。

その 1 、その 2 の分とあわせて、この 3 つのポイントで、 Python のスコープに関するルールは大方押さえられるかと思いますので、参考にしてみてください。


おまけ

現在のスコープの中に存在する名前とそこにひもづけられた参照をチェックする関数として次のふたつの関数が用意されています。

  • locals()
  • globals()

たとえば次のようにするとローカル空間、グローバル空間に存在する名前を辞書として確認することが可能です。

def show_names():
    x = 5
    y = 6
    print locals()  # => {'x': 5, 'y': 6}
    print globals() # => グローバルの名前一覧

0 件のコメント: