1. ホーム 
  2. 備忘録 
  3. Python

名前空間とスコープ

名前空間とスコープ

名前空間とは、変数名や関数名などの名前とオブジェクトを対応付けることである

名前空間に対応付けられている名前を直接参照できる範囲のことをスコープという

例えば関数の中で定義された変数は、関数の外から直接参照することはできない

Pythonのスコープには大きく分けて3種類あり、ビルトインスコープ、グローバルスコープ、ローカルスコープと呼ばれる

PythonではC#などの言語ほど細かくスコープを生成しないため、例えばif文やfor文などではスコープは生成されないことに注意する


ビルトインスコープ

ビルトインスコープは一番外側のスコープであり、組み込み定数や組み込み関数などが含まれる

例えば True False や、None などの組み込み定数や、print関数やmax関数などの組み込み関数はプログラムのどの領域でも使用することができる


グローバルスコープ

グローバルスコープはビルトインスコープの内側のスコープで、1つのモジュール全体を含む

グローバルスコープはモジュールスコープとも言い、そのモジュール内のどこからでも参照できることを指す

例えば関数やクラスの外で定義された変数はその Python ファイル内のどこからでも参照できる

現在のモジュールで有効な名前空間は globals() を呼び出すことで確認できる


ローカルスコープ

ローカルスコープはグローバルスコープのさらに内側のスコープで、関数やクラスの中の領域を指す

ローカルスコープの名前には、同一のローカルスコープの中からしか参照できない

現在のローカルスコープ内で有効な名前空間は locals() を呼び出すことで確認できる


global文

ローカルスコープ内で宣言した変数をグローバルスコープのものとして扱いたいときは global文 を使用する

global文 の書き方を以下に記載する


def test_func1():
    global animal
    animal = 'cat'


def test_func2():
    global animal
    animal = 'dog'


def test_func3():
    animal = 'rabbit'


def print_func():
    # animal をローカルで定義していない場合はグローバルスコープを見に行く
    print(animal)


# cat に書き換え
test_func1()
print_func()  # cat

# dog に書き換え
test_func2()
print_func()  # dog

# ローカルスコープでの書き換えなので反映されない
test_func3()
print_func()  # dog
"""
上の例のように、グローバルスコープに animal が定義されていなくても使えるが、
基本的にはグローバルスコープで animal を宣言しておいて、
ローカルスコープでグローバルスコープの変数を参照したいときにglobal文を使用する
"""

### エラーケース
name = 'Tarou'  # グローバルスコープとして宣言
def test_func4():
    # name が以降の行でローカルスコープとして宣言されているため、この段階では未定義だとエラーが出る
    print(name)  # UnboundLocalError: local variable 'name' referenced before assignment
    name = 'Hanako'  # ローカルスコープとして宣言
    print('after', name)

test_func4()

nonlocal文

ローカルスコープ内で宣言した変数を、さらに内側のローカルスコープ(関数内関数など)で扱いたいときに nonlocal文 を使用する

nonlocal文 の書き方を以下に記載する


name = 'Tarou'  # グローバルスコープで name を定義


def test_func():
    name = 'Hanako'  # ローカルスコープで name を定義

    def inner_func():
        nonlocal name  # 1つ外側のローカルスコープの name を使用すると宣言
        name = 'Jirou'
        print(name)  # Jirou

    inner_func()
    print(name)  # Jirou

test_func()
print(name)  # Tarou

"""
1つ外側のローカルスコープを使用するだけなので、
グローバルスコープにまで影響していないことに注意する

なお、1つ外側のスコープがグローバルスコープの場合は、
nonlocal文を使用すると以下のエラーがでるので注意
SyntaxError: no binding for nonlocal 'name' found
"""

    参考文献

  1. 【名前空間とスコープ】知っているとエラーが減る?|初心者にもわかりやすく解説【Python入門・応用18】