Python のスコープ その1

何回かに分けて、 Python のスコープのルールについて見ていきたいと思います。

Python の変数がどの範囲でアクセスできるかという「スコープ」に関するルールは、まとめると次の 3 ポイントになるかと思います。

  1. 関数/クラス/モジュールで区切られる
  2. 参照の順番は「 LEGB 」
  3. 宣言はスコープの先頭に巻き上げられる

順に説明していきます。

1. 関数/クラス/モジュールで区切られる

Python には、関数、クラス、モジュールというコードの単位がありますが、それらがスコープの区切り目になります。

具体的には、関数の中と外、クラスの中と外、モジュールの中と外でスコープが異なります。

たとえば、次のコードを見てましょう。

margin = 10

def add_margin(x):
    margin = 50
    return x + margin

print add_margin(30)  # => 80

print margin  # => 10

このコードでは margin という名前が add_margin() という関数の外側と内側に存在しますが、関数の外と中は別の名前空間となるため、これらはまったくの別物です。

クラスの場合も同様です。

Const = 3

class MyMath(object):
    Const = 3.14

print Const  # => 3

MyMath の中の Const と外の Const は別物です。

モジュールというのは、ここではスクリプトファイルのことを指して言っています。

たとえば、次のような moduleA.py と moduleB.py 、 2 つのファイルがある場合を考えてみましょう。

# moduleA.py
greeting = "Hi!"
# moduleB.py
greeting = "Ciao!"

次の main.py からそれらを import してみます。

# main.py
import moduleA
import moduleB

print greeting  # => エラー
print moduleA.greeting  # => Hi!
print moduleB.greeting  # => Ciao!

すると、 moduleAmoduleB の中のトップレベルに置かれた greeting という名前はそれぞれ moduleA.greetingmoduleB.greeting でアクセスすることとなります。つまり、モジュール単位で名前空間が区切られます。

from moduleA import greeting というように from ... import ... を使ってインポートをしてきた場合は名前を衝突させることができますが、基本的には名前空間はモジュール単位で別々になります。

つづいて、「2. 参照の順番は「LEGB」」というポイントについて見ていきましょう。