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
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
- 関数自体を初期状態で変数に買格納して、利用するときは同じ関数名で関数内関数を呼び出せま。
というのは、以下の意味でしょうか。
関数自体を初期状態で変数に格納して、利用するときは同じ関数名で関数内関数を呼び出せます。
これは正しくありません。
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
総合スコア24668
0
ご提示の例だとおっしゃる通り、「クラスをインスタンス化して、そのメソッド呼び出すのと同じよう」だと私にも見えます。一方で関数とクラスの違いは、
- 関数の場合、
a
への参照は外側のsample
関数のネームスペース(locals()
で確認できる空間)に保持される。 - 一方クラスの場合、
a
への参照はsample
クラスのインスタンス変数(つまりself.a
)に保持される。
ところだと私は考えます。しかし、私もこの回答をまとめながら「だから何?」と本質的な違いを見出せずにいます。(単純な呼び出し効率だけを考えると関数の方が優位だと思いますな気がする。しかしそれを体系立てて説明できない。。。)深い&示唆にとむ質問だと感心しています。
投稿2021/06/20 03:29
編集2021/06/20 04:15総合スコア6142
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
部分適用に高階関数を活用するときのお話ですね。
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総合スコア35668
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。