Pythonの4つのスコープと「グローバル宣言」「nonlocal宣言」について

スコープとはプログラムの有効範囲を示す言葉で、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のスコープを理解していないと、予想と異なる値が表示されることもあるので、スコープの使い方をしっかりと覚えましょう。

Related