未だに初心者抜け出せないウーマンです。
久々になんじゃこりゃとなった書き方に出会ったので備忘録として記事にします。
関数の中に関数、引数がないやんけ。。。
こんな書き方してるコードに出会いました。
def function_a(x):
def function_b(y,z):
ー中略ー
return b_return
return function_b
function_aの返り値がfunction_bやけど、function_bのところに引数ないやん????
これは何???????
無論、function_bという定数がほかのところにあるわけではありません。
そんなわけで調べました。
「python 関数の中に関数 引数 ない」
みたいなかんじで。
当然そんな感じじゃ出てこなかったんですけど、答えは見つかりました。
ありがとう、グーグル先生。
クロージャというらしい
こういう書き方するやつのことを、「クロージャ」というらしいということがわかりました。
調べを進めていきます。
こういうときはウィキペディアの解説が一番わかりやすかったりするので参照します
https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3
が、
今回はなにやら難しいことがいっぱい書いてあります。
その他いろいろ読みましたがjavascript用の解説が多いように感じます。
みんな引っかかるようなものなのかな?
ざっくり以下のようなものだと理解しました
- 関数の中に関数を書く
- 状態を保持できる関数
まだまだ理解が追い付いていないので、pythonではどうなんか、ってことを見つつ勉強していきます。
pythonにおけるクロージャーの使い方って
勉強させていただいたのはこのページです。
ほんとわかりやすいので私のつたない文書読む前にまず読んでほしい。
https://pg-chain.com/python-closure
初めのコードを具体化してみていきます。
def function_a(x):
def function_b(y,z):
b_return = x + y + z
return b_return
return function_b
単純に足し算して値を出してくれるような関数です
これを使う時どうするか、という話ですが、
まずはfunction_aを普通に使う時みたいに書いてみます。
closure = function_a(10)
これだけ見ると定数closureにfunction_aの答えを入れたように見えるのですが
クロージャの場合は違ってきます。
このclosureは「クロージャ変数」というものになっている、とのことです。
だってyとzの値まだわかってないし、答えだせないですよね。
このときclosureはx=10という状態を保持したクロージャ変数になっています。
そしてここからどうするか。
ans = closure(1,2)
print(ans)
# ans = 13
ans = closure(2,3)
print(ans)
# ans = 15
クロージャ変数closureに引数を渡して実行しちゃう!
なんじゃそりゃ!
でも、そう使うんだそうです。
この時closure(1,2)を実行するとfunction_b(1,2)を実行したのと同じこととなって
x+y+zは10+1+2となり答えは13となります。
また、
x = 10という値は保持された状態になっているのでもう一度closureを呼び出し、
ans = closure(2,3)とすると答えは15となるんですねえ。
便利!なのかな?
使い方はわかった!
状態を保持して置けること、
実行したいタイミングをずらせること
なんかが嬉しかったりするのかな。
終わりに
私と同じように
「python 関数の中に関数 引数 ない」
と検索した人がこの記事にあたって
偉大なる参考ページ様で理解を深められることを祈っております。