Pythonの基礎 - クロージャ

提供:MochiuWiki : SUSE, EC, PCB
2021年11月24日 (水) 17:28時点におけるWiki (トーク | 投稿記録)による版 (文字列「<source」を「<syntaxhighlight」に置換)
ナビゲーションに移動 検索に移動

概要

Pythonには、クロージャというものが存在する。

クロージャとは、参照環境を伴ったような関数、あるいはその関数への参照のことを指す。(関数内関数やC/C++/C#の関数オブジェクトに似ている)
関数内の変数を扱う時、その関数が宣言された時のもの(スコープ)によって実行されるというような説明もできる。


クロージャを理解する

まず、クロージャを理解するために、関数内関数を見ておく。

<syntaxhighlight lang="python">
def OuterFunc(a, b):
    def InnerFunc():
        return a + b

    return InnerFunc()

print(OuterFunc(2, 3))

# 出力
5
</source>


クロージャは、上記のサンプルコードを次のように変更する。
以下の例では、OuterFunc関数の戻り値が、InnerFunc関数を呼び出すのではなく、丸括弧を使用せずにInnerFuncオブジェクトを記述している。
このサンプルコードを実行すると、InnerFuncオブジェクトのアドレスが返される。

これは、まだInnerFunc関数が実行されていない状態である。
この状態を記憶して、後で使用することができるものがクロージャである。ここでは、InnerFuncがクロージャになる。

<syntaxhighlight lang="python">
def OuterFunc(a, b):
    def InnerFunc():
        return a + b

    return InnerFunc

print(OuterFunc(2, 3))

# 出力
<function outer_function.<locals>.inner_function at 0x10d86b7b8> 
</source>



クロージャの実行

クロージャを実行するには、次のように行う。
以下の例では、OuterFunc関数をfuncオブジェクトに代入している。これに、丸括弧()を付けてfuncオブジェクトを実行している。

<syntaxhighlight lang="python">
def OuterFunc(a, b):
    def InnerFunc():
        return a + b

    return InnerFunc

func = OuterFunc(2, 3)
print(func())
# 出力
5
</source>


次に、長方形の面積を計算するサンプルコードを記述する。(横(width)と縦(height)を乗算)
以下の例では、引数に横(width)を与えるAreaCalc関数を定義して、その中に縦(height)を引数を定義して面積を計算するAreaCalcFunc関数を定義している。
戻り値は、丸括弧()を外したAareaCalcFuncオブジェクトを返す。(クロージャになっている)

まず、2種類の横の数値を与えた後、オブジェクト変数ac1とac2にAreaCalcFuncオブジェクトを代入している。
このオブジェクト変数ac1とac2に丸括弧()を付けて縦の数値を与えることで計算が実行される。

<syntaxhighlight lang="python">
def AreaCalc(width):
    def AreaCalcFunc(height):
        return width * height

    return AreaCalcFunc

# widthが25と50の場合を計算
ac1 = AreaCalc(25)
ac2 = AreaCalc(50)

# heightを10として面積を求める
print(ac1(10))
print(ac2(10))

# 出力
250
500
</source>