Pythonの4つのスコープと「グローバル宣言」「nonlocal宣言」について
2019.08.18
スコープとはプログラムの有効範囲を示す言葉で、Pythonには大きく4つのスコープ(LEGB)があります。
- ローカルスコープ / Local
- エンクロージングスコープ / Enclosing
- グローバルスコープ / Global
- ビルドインスコープ / Builtin
それぞれのスコープの範囲を図でまとめると次のようになります。
「あれ?エンクロージングスコープはどこ?」と気になると思いますが、その理由は後述します。
それでは、Pythonにおけるスコープについて解説していきます。
Pythonの4つのスコープ(LEGB)
4つのスコープについて、それぞれ説明していきます。
ローカル(Local)スコープ
最も範囲が狭いスコープで、関数内でのみ有効なスコープです。
関数内の変数をローカル変数といい、ローカル変数をローカルスコープ外で呼び出すと、次のようなエラーが起こります。
Python / ローカルスコープ
def number():
x = 2 // ローカル変数
print(x)
number()
print(x)
# 出力結果
2
NameError: number 'x' is not defined
上記のように、ローカル変数をローカルスコープ外で呼び出そうとすると、「そんな変数ないですよ(NameError: name ‘x’ is not defined)」というエラーが表示されます。
エンクロージング(Enclosing)スコープ
エンクロージングスコープは少し複雑で、かつ全く出てこないので覚えなくて問題ないです。
端的に答えると、エンクロージングスコープは関数の外側にあるローカルスコープです。
ただ、ほとんどの場合はエンクロージングスコープと言わずにローカルスコープと言います。
使われず、かつ複雑なスコープなので覚える必要はないです。
グローバル(Global)スコープ
グローバルスコープは最も広い範囲のスコープで、モジュール(ファイル)内であればどこでも呼び出すことができます。
他の言語を習得された方はPythonのグローバル変数は注意が必要で、Pythonのグローバルスコープはモジュール(ファイル)内までしか呼び出すことができません。
Pythonで他のモジュールにあるグローバル変数(モジュール変数)を呼び出すには、モジュール変数が記載されているモジュールをインポート(import)する必要があります。
グローバルスコープは下記のような記述になります。
Python / グローバルスコープ
x = 2 // グローバル変数
def number():
print(x)
number()
print(x)
# 出力結果
2
2
関数内外、モジュール内であればどこでもグローバル変数を呼び出すことができます。
ビルドイン(Builtin)スコープ
ビルドインスコープは、あらかじめ設定されている変数で、全てのモジュールで呼び出すことができます。
ビルドインスコープの特徴としては、他のスコープと異なり変数を追加することはできません。
ビルドインスコープは下記のような変数が該当します。
- int
- str
- len
- range
- locals
- globals
上記は、あらかじめpythonに組み込まれている変数です。
ローカルスコープからグローバル変数へアクセスする「グローバル(global)宣言」
先ほど、「ローカルスコープの範囲は関数内」と言いましたが、実は「グローバル(global)宣言」を用いることで、ローカルスコープからグローバル変数にアクセスすることができます。
具体的には下記のように記述します。
Python / グローバル宣言
x = 2 // グローバル変数
def number():
global x // グローバル宣言
x = 4
print(x)
number()
# 出力結果
4
上記のように、global宣言を用いることでローカルスコープからグローバル変数にアクセスすることができます。
関数の外側の関数の変数を変更できる「nonlocal宣言」
Pythonは関数内に関数やクラスを定義できるのですが、関数の外側のローカル変数にアクセスする方法が「nonlocal宣言」です。
言葉だと分かりずらいので、nonlocal宣言を用いたプログラムを記述してみます。
Python / nonlocal宣言
def number():
x = 2
def new_number():
nonlocal x
x = 4
print("one:", x)
new_number()
print("two:", x)
number()
# 出力結果
one:4
two:4
上記のプログラムでnonlocal宣言をしないと、twoの値が「2」と表示されます。
まとめ
Pythonのスコープをまとめると次のようになります。
- Pythonのスコープは「ローカルスコープ」「エンクロージングスコープ」「グローバルスコープ」「ビルドインスコープ」の4種類がある
- ローカルスコープからグローバル変数にアクセスするには「グローバル宣言」を用いる
- 関数の外側の関数の変数にアクセスするには「nonlocal宣言」を用いる
Pythonのスコープを理解していないと、予想と異なる値が表示されることもあるので、スコープの使い方をしっかりと覚えましょう。