何回かに分けて、 Python のスコープのルールについて見ていきたいと思います。
Python の変数がどの範囲でアクセスできるかという「スコープ」に関するルールは、まとめると次の 3 ポイントになるかと思います。
- 関数/クラス/モジュールで区切られる
- 参照の順番は「 LEGB 」
- 宣言はスコープの先頭に巻き上げられる
順に説明していきます。
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!
すると、 moduleA
、 moduleB
の中のトップレベルに置かれた greeting
という名前はそれぞれ moduleA.greeting
、 moduleB.greeting
でアクセスすることとなります。つまり、モジュール単位で名前空間が区切られます。
from moduleA import greeting
というように from ... import ...
を使ってインポートをしてきた場合は名前を衝突させることができますが、基本的には名前空間はモジュール単位で別々になります。
つづいて、「2. 参照の順番は「LEGB」」というポイントについて見ていきましょう。