Pythonでは、関数内に関数を定義できます。こうすると関数自体を初期状態で変数に買格納して、利用するときは同じ関数名で関数内関数を呼び出せます。
これはクラスをインスタンス化して、そのメソッド呼び出すのと同じように見~~合~~えます。関数内関数を利用する利点を教えてください。
Python
1# 関数内の関数 2N = 1 3def sample(a): 4 def sample(b): 5 return a + b 6 return sample 7 8sample_test = sample(N) 9 10for i in range(10): 11 print(sample_test(i)) 12
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
下記のような質問は推奨されていません。
- 質問になっていない投稿
- スパムや攻撃的な表現を用いた投稿
適切な質問に修正を依頼しましょう。
回答3件
1
- 関数自体を初期状態で変数に買格納して、利用するときは同じ関数名で関数内関数を呼び出せま。
というのは、以下の意味でしょうか。
関数自体を初期状態で変数に格納して、利用するときは同じ関数名で関数内関数を呼び出せます。
これは正しくありません。
Pythonの関数定義は実行文です。したがって、関数内関数は外側の関数が実行されるたびに新しく生成されます。
以下を見て理解してください
Python
1>>> def generate_func(x): 2... def inner_func(y): 3... return x + y 4... return inner_func 5... 6>>> func_i = generate_func(42) 7>>> 8>>> func_l = generate_func([0, 1, 2]) 9>>> 10>>> print(func_i(10)) 1152 12>>> print(func_i(['a', 'b'])) 13Traceback (most recent call last): 14 File "<stdin>", line 1, in <module> 15 File "<stdin>", line 3, in inner_func 16TypeError: unsupported operand type(s) for +: 'int' and 'list' 17>>> print(func_l(10)) 18Traceback (most recent call last): 19 File "<stdin>", line 1, in <module> 20 File "<stdin>", line 3, in inner_func 21TypeError: can only concatenate list (not "int") to list 22>>> print(func_l(['a', 'b'])) 23[0, 1, 2, 'a', 'b']
- クラスをインスタンス化して、そのメソッド呼び出すのと同じように見合えます。
もともと機能が違いますので、利点云々の話ではないと理解してください。
投稿2021/06/20 07:19
総合スコア24635
1
ご提示の例だとおっしゃる通り、「クラスをインスタンス化して、そのメソッド呼び出すのと同じよう」だと私にも見えます。一方で関数とクラスの違いは、
- 関数の場合、
a
への参照は外側のsample
関数のネームスペース(locals()
で確認できる空間)に保持される。 - 一方クラスの場合、
a
への参照はsample
クラスのインスタンス変数(つまりself.a
)に保持される。
ところだと私は考えます。しかし、私もこの回答をまとめながら「だから何?」と本質的な違いを見出せずにいます。(単純な呼び出し効率だけを考えると関数の方が優位だと思いますな気がする。しかしそれを体系立てて説明できない。。。)深い&示唆にとむ質問だと感心しています。
投稿2021/06/20 03:29
編集2021/06/20 04:15総合スコア6137
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
1
ベストアンサー
部分適用に高階関数を活用するときのお話ですね。
Pythonの機能上は、関数にできてクラスにできないことはほとんど無いでしょう。(註)
ですので、『部分適用するとき、高階関数とクラスのどちらを使うべきか?』という議論は、
結局のところ『関数とクラス、どちらを使うべきか?』という一般論に帰着すると思います。
以降、個人的意見です。
一般にクラスの方が機能がリッチなので、次のように判断します。
0. まずは関数を使う
0. 関数で実現が難しい場合、あるいはそのような拡張が見込まれる場合はクラスを使う
上述のマイルールに従えば、ご質問の機能は関数で実現します。
例えば、『任意の値に対し、四則演算を部分適用する機能』を作るとしましょう。
これを関数で実現するのは面倒です。
Python
1def make_add_a(a): 2 def add(b): return a + b 3 return add 4 5def make_mul_a(a): 6 def mul(b): return a * b 7 return mul 8 9...
あるいは
Python
1def make_op_a(a): 2 def add(b): return a + b 3 def mul(b): return a * b 4 ... 5 6 return add, mul, ...
前者は記述が冗長ですし、後者は呼び出し側が必要な戻り値を選択する必要があります。
クラスを使って書いた場合、これらの問題は解消します。
Python
1class Op: 2 def __init__(self, a): 3 self._a = a 4 5 def add(self, b): 6 return self._a + b 7 8 def mul(self, b): 9 return self._a * b 10 11 ...
このような場面では、クラスを使った方が素直でしょう。
註
細かい話をするなら、インスタンスそのものをクラス側の操作でキャストする方法は無いです。
Python
1class Add: 2 def __init__(self, a, b): 3 self._a = a 4 self._b = b 5 6 def __call__(self): 7 return self._a + self._b 8 9 def __int__(self): 10 return self() 11 12assert not isinstance( Add(1, 2), int) 13assert isinstance( Add(1, 2)(), int) 14assert isinstance(int(Add(1, 2)), int)
私が見落としているだけで、他にも機能上実現できない点はあると思います。
投稿2021/06/20 03:13
編集2021/06/20 03:17総合スコア35628
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
関連した質問
Q&A
解決済
idtwiの動作を再現するTwitterAPIの使い方について
回答1
クリップ0
更新
2023/03/21
Q&A
解決済
return 文でsyntax error となるのは何故?
回答2
クリップ0
更新
2023/03/21
Q&A
解決済
1986-1-12 00:00:00.0 と出力されてしまうのを, SimpleDateFormat("yyyy-MM-dd");のパターンに直したい
回答2
クリップ0
更新
2023/03/24
Q&A
受付中
音声の離散フーリエ変換後にノイズが入ってしまう
回答2
クリップ2
更新
2023/03/15
Q&A
解決済
複数の入力欄の文字数を個別にカウントしてリアルタイムに表示する方法
回答1
クリップ0
更新
2023/03/22
意見交換
受付中
eclipseはオワコンですか?
回答20
クリップ0
更新
2023/03/16
Q&A
受付中
Python3.11.1:原因不明の 挙動不審を、何とかしたい。
回答2
クリップ1
更新
2023/03/23
Q&A
受付中
モジュールのビルドが失敗する。
回答0
クリップ0
更新
2022/07/06
同じタグがついた質問を見る
Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。