質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
関数型プログラミング

関数型プログラミングとは、関数を用いて演算子を構築し、算出し、コンピュータプログラムを構成する枠組みです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

6回答

2419閲覧

関数内関数を積極的に使うシチュエーションがわからない・意義がいまいち理解できない

komicool

総合スコア24

関数型プログラミング

関数型プログラミングとは、関数を用いて演算子を構築し、算出し、コンピュータプログラムを構成する枠組みです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

3クリップ

投稿2019/05/06 13:48

Pythonの入門本で学習を進めている中で、関数内関数の存在意義がよくわからなかったので質問させてください(仕組みや挙動自体については理解できますが、積極的に使うシチュエーションがよくわからないという趣旨の質問です)

入門本にあるのは以下のようなソースコードなのですが

python

1def outer(a, b): 2 def inner(c, d): 3 return c + d 4 return inner(a, b)

シンプルに以下のように書くか、少し長めの関数であればわざわざ内部関数として定義せずに
通常の関数としてinnerも定義してouter関数内で使い回せばいいよう(そのほうが他の関数からも
参照できてコードの省略になりそう)な気がしてしまいます。

python

1def outer(a, b): 2 return a + b

繰り返しにはなりますが、どのような場合に関数内関数を使うメリットがあるか
ご教示願えますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

① 外側の関数のローカル変数にも内側の関数からアクセス出来る
② 内側の関数名が外から見えず、他から使われないことが保証できるので読むとき楽
①+② ⇒ ある関数内でのみ必要な処理を気軽にコンパクトに書ける

②は、「ローカル変数の意義が分からない。全部グローバル変数でいいのでは?」というのに通じる話だと思います。

関数の外に出して独立した関数にすべきか、内部関数にすべきかは、関数の仕様を考えた時点で自然に決まると思います。

あとは、①の応用として、他の方の回答にあるクロージャーですね。クロージャーを使うためには、「外側の関数のローカル変数を参照できる内部関数」ないしそれ相当の機能が必要です。

投稿2019/05/06 15:13

編集2019/05/07 01:12
otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2019/05/07 01:11 編集

3. Pythonの関数は第一級関数であるため外側の関数fのローカル関数gをfから別の関数へ渡したりfの戻り値に返したりできる。そのようにして用いられたgはたとえfがreturnした後であってもfのローカル変数をアクセスし続けられる。 といった第三の説明を仮定しますと、自分はクロージャーの意味を、otnさんが挙げておられる1と上述した3を包含した概念として捉えています。そのため > あとは他の方の回答にあるクロージャーです の一文がちょっとひっかかりました。つまりotnさんの1は既にクロージャーの重要な性質を述べておられるような気がしたのです。いかがでしょうか? --- すみません、上のコメント取り消します。別に不自然さはないと思いなおしました。
otn

2019/05/07 01:13

ちょっと記述を修正しました。ついでに誤記を訂正。
komicool

2019/05/12 14:08

大変簡明な回答でわかりやすかったです(BAにしようかとても迷いました)。ご回答ありがとうございました。
guest

0

Pythonでよく使われるシチュエーションは引数付きのデコレータでしょうか。

http://flask.pocoo.org/docs/1.0/quickstart/

に登場するデコレータapp.routeの実装、Flaskクラスのrouteメソッドを見ると関数内関数が登場します。

https://github.com/pallets/flask/blob/1.0.2/flask/app.py#L1224

「「引数として渡された値を束縛した関数」を返す関数」を実装するので関数内関数が自然ですね。

投稿2019/05/07 02:43

quickquip

総合スコア11038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

komicool

2019/05/12 14:11

参考になりました。Flaskはまだ触れていないのですが例として適当なものを紹介してくださり助かりました。デコレータは今後おりを見て使っていきたいと思います
guest

0

なんつーか、質問者さんに同感です。

まず、関数/サブルーチンてのは、機能を分割して
わかりやすいプログラムにするのが目的ですよね。
または、繰り返して使う処理を取り出して
関数/サブルーチンにするみたいなこともしますな。

翻って関数内で(関数内でしか使わない)同じ処理が
散見される場合は使い道があるようにも感じます。
ただ、その場合は機能分割を見直した方が
いいかもしれないという不安はあります。

ちなみに、自分が使う可能性があるとしたら、
処理で使用する関数のパラメタに関数を渡す時
くらいだと思いますが、無名関数が使えるようなら
その必要もないと考えます。

投稿2019/05/06 15:45

takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2019/05/07 02:59

pythonのlambda式は縛りがきつい(単一の式しか書けない)ので、 >無名関数が使えるようなら >その必要もないと考えます。 は少し難しいかもしれません。
takasima20

2019/05/07 14:40

アドバイスありがとうございます。 Python慣れてないのがバレバレですね。(汗
komicool

2019/05/12 14:11 編集

回答ありがとうございます!私も質問時点では利用意義を見出せていなかったのですが、他の皆さんの回答を読んでデコレータでの利用は少しありだなと思い直しました
guest

0

呼び出し元のスコープにある幾つもの変数に依存するとき、というのがまっさきに思い浮かぶ活用例だと思います。

python

1def g(a, b, c, d, e): 2 print(a + b + c + d + e) 3 4def f(): 5 a, b, c, d, e = 1, 2, 3, 4, 5 6 g(a, b, c, d, e) 7 8def f(): 9 def g(): 10 print(a + b + c + d + e) 11 12 a, b, c, d, e = 1, 2, 3, 4, 5 13 g() 14

結果は同じですが、どちらが理にかなっているのかは言うまでもないでしょう。

投稿2019/05/06 14:09

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

komicool

2019/05/12 14:07

参考になりました。ご回答ありがとうございました!
guest

0

ベストアンサー

内部関数を返し、クロージャを利用するのが良くある活用法です。

Python

1def make_who_say(who): 2 def who_say(sentence): 3 print(f'{who}: {sentence}') 4 5 return who_say 6 7 8tom_say = make_who_say('Tom') 9mary_say = make_who_say('Mary') 10 11tom_say('Hi, Mary.') 12mary_say('Hi, Tom.')

実行結果 Wandbox

plain

1Tom: Hi, Mary. 2Mary: Hi, Tom.

通常の関数としてinnerも定義してouter関数内で使い回せばいいよう(そのほうが他の関数からも

参照できてコードの省略になりそう)な気がしてしまいます。

おっしゃる通りで、他の方法で充分簡潔に代替できる際に積極的に用いることは無いでしょう。

追記

関数の可視性を制御するのはモジュールの役割であって、
それを内部関数で実現するのは本質的ではないように個人的には思います。

共通の変数にアクセスする関数が多くあるのなら、クラスを組めば良いでしょう。
関数内の変数に強く依存したコードを書くなら、コメントをしっかり付けてべた書きすれば良いでしょう。
何度も同じ処理をする必要があるのなら、それが関数内変数に依存するのは設計に問題がありそうです。

内部関数は高階関数を組むときを除いて積極的に使うものでは無いと、私はやはり思うのです。

投稿2019/05/06 13:56

編集2019/05/07 04:17
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

komicool

2019/05/12 14:10 編集

質問した後 学習を進めまして、クロージャ・デコレータでの利用が一番合理性があると自分でも感じました。一番最初に回答をくださったこと、回答が要領を得ていることからBAとさせていただきました。ありがとうございました。
guest

0

外では使わない関数を内部で定義します。同じ名前の関数、この場合はinnerが複数のoutterにあっても良く、同じ名前を使った方が分かりやすい場合もあります。デコレータはどの関数でも同じ名前になり、その例と言えます。内部関数、class みたいな考え方ない場合、funcに対して、funcinit, funccopy_contractor みたいな名前を付け、しかもその名前がどこからでも見えるために、funcinitとfunc_init, funcinit_init の間の関係について悩むようなことになります。

投稿2019/05/14 01:45

gm300

総合スコア580

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問