Menu/Prof
スズキマコト
自由人
元々は楽器屋のギター兄ちゃん。
趣味でプログラミングしてるうちに
本職になってしまった人。

過去に喋っていた言語
c pascal Assembler
perl PHP Python Ruby など
javascriptなどは都度必要に応じて。
最近Mac買ったのでswift勉強してます。

体ぶっ壊して死にかけたので人生RESET中。
おすすめ記事!

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

Some visuals are licensed via Canva Pro (includes commercial rights).
Usage complies with Canva’s license terms at the time of use.
License policy: canva.com/policies/content-license-agreement

contents

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_functionはouter_functionの中で定義されているため、そのスコープはouter_function内に限られます。これは、inner_functionがouter_functionのローカルスコープに存在するということを意味します。

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

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

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

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

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

シェアしてくれると喜びます
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

makotoのアバター makoto Blogger&YouTuber

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

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

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

現在 ほぼ自由人。

contents