はじめに
たまに出てくるクロージャですが、理解するまで若干こんがらがるので簡単なサンプルを載せてみました。
クロージャとは、受け取った引数をセットした状態で呼び出し元にオブジェクトとして返し必要なときに実行するもの、と考えればいいと思います。
なかなかピンとこないかもしれませんが、普通の関数であれば処理結果をそのまま呼び出し元にreturn しますが、クロージャの場合、処理結果ではなく引数をセットした形で一旦、オブジェクトとして返す、というものですね。
関数内関数の少し難しい版ってところでしょうか。
オブジェクトとして受け取った呼び出し元は、実際に実行したいタイミングで引数を付けて実行してあげることで処理結果を得る、という流れになります。
イメージとしては、予めコードをセットした状態で用意しておき、使いたいタイミングで呼び出し結果を得る、と考えればわかりやすいかなと思います。
基本的な使い方
基本的な形は以下になります。
def outer_func(a, b):
def inner_func():
return a + b
f = outer_func(5, 6)
print(f())
outer_funcの引数a,bをinner_funcにセットしてあげて、returnで「inner_func」の形で返します。
ここで注意すべき点が「return inner_func()」ではないということです。
「()」を付けてしまうと関数が実行されてしまうので、「()」は付けてはいけません。
「return inner_func」の形で記述してあげます。
たまに見かけるのが、クロージャにはパラメータを与えません、とか書籍にも出てきますが、自分的にはパラメータを与えているコードも見ますし、そんなことないんじゃないかぁと思ったりもします。
実践的な使い方
実際、どういう時に使うのかが気になるところですが、円周率を使って円の面積を求めるとか、単純にレクタングルの面積を求めるなどがありますが、なかなか「これだっ!」っていう使い方が見つけにくかもしれません。
因みに円の面積を求める場合はこんな感じです。
def circle_area(pi):
def _calc(radius):
return radius * radius * pi
return _calc
calc1 = circle_area(3.14)
calc2 = circle_area(3.1415926535)
print(calc1(10))
print(calc2(10))
最初に円周率をセットしておいて、後で使う時にパラメータで半径を渡している形ですね。
最初に円周率をセットする際に「3.14」にするのか、それとももう少し細かく「3.141592」にするのかといった違いです。
注意点
クロージャは関数内関数とは別物ですので、使う際は以下の点に注意しましょう。
クロージャを包み込んでいる外側の関数(エンクロージャー)は処理結果を返すのではなく、内側の関数(クロージャ)をオブジェクトとしてreturn する。
ちょっとわかりにくいかもしれませんね。
ただ、通常の関数であれば関数内の処理結果を返しますが、クロージャの場合は処理結果ではなく、クロージャを包み込んでいる外側の関数の引数をセットした形でオブジェクトとしてreturnする、ということになります。
言ってみれば、料理でいう仕込みを終えたところで止めているといった感じでしょうか。
処理結果である料理はまだお客さんには出しませんよ~、っという感じで(笑)。
まとめ
通常の関数であれば呼び出した時点ですぐに結果を得られますが、クロージャの場合一旦処理コードをセットしておき、実際に実行したい時点で実行する形になります。
処理結果の精度を分けたい時に使えるかと思いますが、重要度的には少し低めになりそうですね。
上手く使っていければと思います。
コメント