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() は呼び出しのタイミングでエラーが上がってしまいます。

myfunc1() のように print 文のあとに C への代入処理などがなければ print 文は問題なく動くのですが、 myfunc2() のように print 文のあとで C に代入していると「代入の前にCを使ってますよね」ということで怒られてしまいます。

これで怒られるということは print 文のところでは「すでにグローバル空間の C への参照が失われている」ということになります。

この意味で、スコープ内で使われる「名前」は巻き上げられ、スコープの先頭で確保される形になっているようです。

ちなみに、Pythonの場合にこの単語を使うかはわかりませんが、いわゆる「巻き上げ」は英語では「hoisting」という単語に相当します。

以上です。

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


おまけ
スコープ内の名前とそれにひもづけられた参照をチェックする関数として次のふたつの関数が用意されています。
locals()
globals()

たとえば次のようにするとローカル空間、グローバル空間に存在する名前を辞書として確認することが可能です。
def show_names():
    x = 5
    y = 6
    print locals()  # => {'x': 5, 'y': 6}
    print globals() # => グローバルの名前一覧

0 件のコメント: