Pythonの変数スコープとは?グローバル変数やローカル変数、nonlocalについて解説

スポンサーリンク

変数スコープは、Pythonプログラマーが変数や関数を扱う前に知っておかなければならない、興味深く、便利で、理解しやすい概念です。

この記事では、スコープとは何か、python が持つスコープの種類、そしてキーワードである globalnonlocal について説明します。

スポンサーリンク

スコープって何?

関数やクラス、ユーザー定義変数のスコープとは、その変数にアクセスできるコードの領域のことです。

関数内で宣言された変数は、その関数の中でのみアクセス可能で、関数の外ではアクセスできませんので、その関数が変数のスコープとなります。

たとえば、次のようなコードです。

def funcx():
    x = 1
    print(x)
    return
 
def funcy():
    y = 2
    print(y)
    return
 
def funcz():
    z = 3
    print(z)
    return

変数 xfuncx で宣言されているので、funcx がその変数のスコープになります。

同様に、y のスコープは funcy で、z のスコープは funcz です。

グローバル変数、ローカル変数、非ローカル変数のスコープを理解します。

Pythonでは、各変数に変数スコープがあります。

つまり、その変数が使用できる境界線が明確に定義されています。

変数が使用される場所によって、変数は異なる種類のスコープを持つことができるので、一つずつ説明しましょう。

1. グローバル変数スコープ

Pythonファイルのどこからでもアクセスできる変数をグローバルスコープと呼びます。

以下のコードを参照してください。

x = 10
print(x)
def func():
    print(x)
    return
 
func()

変数 x はどの関数の外でも宣言されています。

これは、コード全体のどこからでもアクセスできることを意味します。

上の例では、xfunc の中だけでなく、func の外側からもアクセスされます。

出力は

Global: 10
Local: 10

注意: 関数の内部でグローバル変数を操作するのは少し複雑なので、後ほど global キーワードを使用して説明します。

2. ローカル変数スコープ

ある関数の内部で宣言された変数をローカルスコープと呼びます。

この場合、その変数はその関数内でのみアクセス可能であり、関数の外でそのような変数にアクセスしようとすると、同じ名前のグローバル変数がない場合はエラーになる。

def func():
    x = 10
    print(x)

上の関数では、変数 x は関数の内部で作成されているので、 xfunc のローカル変数となります。

したがって、xfunc のローカル変数です。

func の外部から x にアクセスしようとすると、エラーになります。

3. 非局所変数のスコープ

非局所変数のスコープを理解するために、例を挙げよう。

def outer_func():
    x = 10
    print("Outside:", x)
     
    def inner_func():
        print("Inside:", x)
        return
     
    inner_func()
    return
 
outer_func()

関数 outer_func には変数 x があるので、明らかに outer_func にとっては x はローカルです。

しかし、 inner_func にとって、 x は非局所的です。

つまり、 xinner_func にとって局所的ではありませんが、大域的でもありません。

つまり、 inner_func からは、 x を非ローカル変数としてアクセスすることができる。

そして、これが出力です。

Outside: 10
Inside: 10

Note: inner_func から x を操作するのは少し複雑です。

これは、nonlocal キーワードについて説明するときにわかります。

グローバル変数と非ローカル変数の操り方

関数内でグローバル変数や非ローカル変数にアクセスできることはわかりましたが、関数内でその変数を直接操作しようとすると、エラーになります。

例を見てみましょう。

x = 10
def func():
    x += 1
    print(x)
    return
 
func()

論理的には、グローバル変数であり、どこにでもアクセスできるので、xを増加させることができるはずですが、実際の出力はこのようになっています。

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-33-07e029a18d76> in <module>
      5     return
      6 
----&gt; 7 func()


<ipython-input-33-07e029a18d76> in func()
      1 x = 10
      2 def func():
----&gt; 3     x += 1
      4     print(x)
      5     return


UnboundLocalError: local variable 'x' referenced before assignment

UnboundLocalError: local variable ‘x’ referenced before assignment`と表示されています。

Python は x がローカル変数であると仮定して、参照する前に値を代入するように言っています。

x` を出力すればうまくいくことは分かっているので、グローバル変数が関数内で直接変更された場合にこのようなエラーが発生することを意味しています。

Pythonのグローバルキーワード

このエラーを回避するために、グローバル変数のスコープに global キーワードを使用することができます

x = 10
def func():
    global x
    x += 1
    print(x)
    return
 
func()

関数内で x をグローバルに宣言し、Python に x がすでにグローバルスコープで宣言されているので、その x を使用することを伝えていることがわかります。

11

このように、今回は変更された x の値が出力されます。

Pythonのnonlocalキーワード

非ローカル変数のスコープでは、以下のように nonlocal キーワードを使用して、説明したエラーを回避します。

def outer_func():
    x = 10
     
    def inner_func():
        nonlocal x
        x += 1
        print(x)
     
    inner_func()
    return
 
outer_func()

これは inner_func 関数の内部で x が nonlocal であることを Python に伝えています。

(xはグローバルではないので、globalは機能しません)。

出力は

11

おわりに

この記事では、Python のスコープが何を意味するのか、さらにグローバル、ローカル、非ローカル変数が何であり、どのように使用するのかを説明しました。

また、2つのキーワードの使い方を説明しました。

グローバル(global)」と「非ローカル(nonlocal)」という2つのキーワードの使い方を説明し、Pythonのコードでそれらが動作する様子とその出力を見ました。

タイトルとURLをコピーしました