Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Pythonのクロージャ

Pythonのクロージャとは?その解説

Python入門:Pythonにおけるクロージャの解説

今回はプログラミング初心者にわかりにくい概念の1つ、クロージャ(またはクロージャー、英語:closure)について、特にPythonにおけるクロージャについての解説です。

Pythonにおけるクロージャとは?

クロージャの原理や学問レベルの定義などは、ひとまず初心者にはどうでもいいので横におきまして、まずPythonにおけるクロージャの特徴を2つ挙げます。それは、

  • 親関数の引数・変数の情報を受け継ぎ保持する
  • その情報を、自身の情報とともに「外へ持ち出す」

以上の2つです。

この特徴を有する関数を、Pythonにおけるクロージャと呼びます。

この2つの点だけを意識して、次の具体例を見てください。

Pythonのクロージャの具体例

まず次の画像を見てください。

Pythonにおけるクロージャ

これは親関数fnc_paretnの中に、子関数fnc_childを書いたものです。

このように、関数の中にまた別の関数を定義することを関数内関数とか、関数のネストと呼びます。これについては先日解説しましたので読んでおいてください。

さて、上画像のコードは次のようなっています。

def fnc_parent(parent_arg):  # fnc_parentがエンクロージャ
    parent_var=10
    def fnc_child(child_arg):
        print(f'親関数の引数:{parent_arg}、子関数の引数:{child_arg}、親関数自身の変数:{parent_var}')
        return parent_arg+child_arg
    return fnc_child   # fnc_childがクロージャ

child_fnc_obj=fnc_parent(3) 
child_fnc_obj(4)

これを実行すると、

親関数の引数:3、子関数の引数:4、親関数自身の変数:10
7

このようになります。

上コード中のコメントのとおり、今回は、

  • 親関数であるfnc_parentがエンクロージャ
  • その子関数であるfnc_childがクロージャ

となります。

では、子関数fnc_childがクロージャであるとはどういうことなのでしょうか。以下解説します。

クロージャの特徴その1

ここで再び、上記Pythonにおけるクロージャの特徴を確認し直しましょう。それは次の2点でした。

  • 親関数の引数・変数の情報を受け継ぎ保持する
  • その情報を、自身の情報とともに「外へ持ち出す」

今回のコードの実行結果は、

親関数の引数:3、子関数の引数:4、親関数自身の変数:10
7

ですが、この実行結果からして、子関数fnc_childが、その親関数fnc_parentの引数と変数の情報を受け継ぎ保持していることがわかってもらえるでしょう。それが1つめの特徴の意味です。

クロージャの特徴その2

  • 親関数の引数・変数の情報を受け継ぎ保持する
  • その情報を、自身の情報とともに「外へ持ち出す」

次に2つ目の特徴についてですが、上コードの次の部分に着目してください。

child_fnc_obj=fnc_parent(3) 
child_fnc_obj(4)

まず、fnc_parentが引数3をとって実行されます。

次に、引数3の情報がfnc_childに受け継がれます。

そして、その「引数3の情報を受けつぎ保持するfnc_child」がreturn文によって返されます。

結果、fnc_parentは「引数3の情報を受けつぎ保持するfnc_child」となります。

次にそれをchild_fnc_objに代入していますので、child_fnc_objは「引数3の情報を受けつぎ保持する子関数fnc_child」となります。child_fnc_objは関数です。

さて、子関数child_fncは、

child_fnc_obj=fnc_parent(3) 

この時点で、親関数fnc_parentの処理ブロックすらも抜けて、その外に「受け継いだ情報を持ち出している」と考えられます。

これに関して次のコードを見て下さい。

x=10
def fnc():
    x=3
    print(x)

fnc()
print(x)

これを実行すると、

3
10

となります。

xの値は、関数の外と中で設定されていますが、関数が実行されその処理が終了すれば、xの値がもともとの10に戻っていることがわかります。関数内のx=3という情報はその外側には持ち出されていません。これが基本です。

しかしPythonでは、クロージャという概念・仕組みを導入することで、その「持ち出し」を可能としています。

それを示すのが、

child_fnc_obj=fnc_parent(3) 
child_fnc_obj(4)

この部分です。

それゆえ、child_fnc_objは、「親関数の引数3の情報を受けついだ子関数fnc_child」という関数になり、

child_fnc_obj(4)

このように引数「4」をとって実行され、その結果「7」という計算結果が表示されます。

Pythonにおけるクロージャまとめ

最後に以上のことのまとめとして、再びクロージャの特徴の2点を書いておきましょう。

  • 親関数の引数・変数の情報を受け継ぎ保持する
  • その情報を、自身の情報とともに「外へ持ち出す」

この2つの特徴を有する関数が、Pythonにおけるクロージャと呼ばれるものです。

あくまで、これらの特徴を持つ関数だけがクロージャであって、全ての関数内関数(子関数)がクロージャになるわけではありません。

長々とクロージャの解説をしましたが、素人が趣味レベルでプログラミングをするだけならば「クロージャという便利なしくみが用意されいる」とだけ意識していれば十分だと思います。

ただ専門家や上級者の方たちのプログラミング解説などを読むときには、知っておいてほうが都合がいいと思います。

プログラミングを学びIT業界へ転職するなら現役エンジニアから学べるプログラミングスクールTechAcademy [テックアカデミー]でオンライン講座を受講するのが良いと思います。1人で悩みながら学習を進めるよりもわかりやすく、費やす時間も少なく合理的・効率的に学習できるからです。

など各種の講座が用意されています。無料で体験できるテックアカデミー無料体験も用意されています。

愛を分かち合いましょう