Pythonの変数のスコープについて

X
     この記事はプロモーションを含みます
Content

Pythonにおける変数のスコープを理解する

Pythonにおける変数のスコープ(スコープとは、変数が参照可能な範囲のこと)は主に以下の4つのレベルに分けられます。

  1. ローカル(Local): 関数内で定義された変数は、その関数内でのみ参照可能です。
  2. エンクロージング(Enclosing): 外側の関数によって定義された変数が、内側の関数で参照可能です。
  3. グローバル(Global): スクリプト全体で定義された変数は、どこからでも参照可能です。
  4. ビルトイン(Built-in): Python言語自体に組み込まれている変数や関数(例:len, printなど)。

Pythonでは、変数を参照する際には「LEGBルール」(Local -> Enclosing -> Global -> Built-in)に従います。これは、変数が参照される際の探索順序を意味します。

以下に、各スコープについてのサンプルコードを示します。

# グローバル変数(Global Scope)
global_var = "I am a global variable"

def outer_function():
    # エンクロージング変数(Enclosing Scope)
    enclosing_var = "I am an enclosing variable"

    def inner_function():
        # ローカル変数(Local Scope)
        local_var = "I am a local variable"

        # 各スコープから変数を参照
        print(local_var)  # ローカル変数
        print(enclosing_var)  # エンクロージング変数
        print(global_var)  # グローバル変数

    inner_function()

# outer_functionを呼び出す
outer_function()

# ビルトイン関数(Built-in Scope)
print(len("I am a built-in function"))

このサンプルコードでは、outer_function内でinner_functionが定義されています。inner_function内のlocal_varはローカルスコープ、enclosing_varはエンクロージングスコープ、global_varはグローバルスコープに存在します。

最後に、len関数はビルトインスコープに存在する関数です。

このように、Pythonの変数スコープは非常に直感的であり、LEGBルールに従って変数を探索・参照します。

マコト

上記のソースですが outer_function の 中に inner_function がありますよね? この場合 inner_functionそのもののスコープは outer_function の中だけということですか?

じぴ子

はい、その通りです。inner_functionouter_functionの中で定義されているため、そのスコープはouter_function内に限られます。これは、inner_functionouter_functionのローカルスコープに存在するということを意味します。

具体的には、outer_functionの外からinner_functionを直接呼び出すことはできません。以下のようなコードはエラーになります。

# これはエラーになる
inner_function()

このようなエラーを避けるためには、inner_functionouter_functionの外で定義するか、inner_functionouter_functionの戻り値として返すなどの工夫が必要です。

例えば、outer_functioninner_functionを戻り値として返す場合:

def outer_function():
    def inner_function():
        print("I am inner_function.")
    return inner_function

# outer_functionを呼び出して、その戻り値(inner_function)を変数に格納
my_inner_function = outer_function()

# 格納した変数を使ってinner_functionを呼び出す
my_inner_function()  # Output: "I am inner_function."

このように、関数内で定義された関数(inner_function)は、その外側の関数(outer_function)のスコープ内でしか存在しないと考えることができます。ただし、Pythonのクロージャなどを使うと、このような内側の関数を外側からも利用することができます。

Pythonのクロージャってなんだー?

Pythonにおいて、クロージャ(Closure)は外側の関数(エンクロージング関数)によって生成され、内側の関数(ネステッド関数)が外側の関数の変数にアクセスできる特殊な関数の一種です。クロージャを使用すると、内側の関数がその定義が行われたスコープ外でも、外側の関数のローカル変数にアクセスできるようになります。

以下に、クロージャの基本的な使用例を示します。

# エンクロージング関数(外側の関数)
def outer_function(x):
    # 外側の関数のローカル変数
    outer_variable = x

    # ネステッド関数(内側の関数)
    def inner_function(y):
        # 内側の関数が外側の関数のローカル変数にアクセス
        return outer_variable + y

    # ネステッド関数を返す
    return inner_function

# クロージャを生成
closure = outer_function(10)

# クロージャを実行
result = closure(5)  # 10 (outer_variable) + 5 (y) = 15
print(result)  # Output: 15

この例では、outer_functioninner_functionを返しています。inner_functionouter_functionのローカル変数outer_variableにアクセスしています。outer_functionを呼び出して得られたinner_function(ここではclosureとして保存)は、その後独立して呼び出すことができ、outer_variableの値(この場合は10)を”覚えて”います。

このようにして、クロージャを使うと内側の関数が外側の関数のローカル変数にアクセスできるようになり、その変数の値を保持することができます。これにより、関数の振る舞いを動的に変更したり、状態を持つ関数を作成することが可能になります。

  • URLをコピーしました!

この記事を書いた人

makotoのアバター makoto Blogger&YouTuber

サーバー管理者として17年ほど仕事でサーバー触ってました。
www,mail,dns,sql各鯖をすべてFreeBSDで運用してましたが現世ではかなりレアなタイプになるみたいですね笑

viやシェルスクリプトとかperlとかgccとかFreeBSDとか実はbashよりtcshが好きとか時々寝ぼけるのは
その名残でしょう。

今まで縁の下の力持ち的な他人のためにプログラムを書き他人のためにサーバー構築し他人のためにWEBサイトを創る的な世界から
自分の好きなことに集中できる環境は実に気持ち良いですね。
現役は引退済みなので難しいことはやりませんしやれません。

現在 ほぼ自由人。

Content