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

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

新規登録して質問してみよう
ただいま回答率
85.53%
Python

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

Q&A

解決済

3回答

9059閲覧

Pythonの関数内関数の利点は何ですか?

teefpc

総合スコア111

Python

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

3グッド

4クリップ

投稿2021/06/20 01:59

編集2021/06/20 09:39

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
kipipipi, YouheiSakurai, LouiS0616👍を押しています

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

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

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

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

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

guest

回答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

ppaul

総合スコア24666

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

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

0

ご提示の例だとおっしゃる通り、「クラスをインスタンス化して、そのメソッド呼び出すのと同じよう」だと私にも見えます。一方で関数とクラスの違いは、

  • 関数の場合、aへの参照は外側のsample関数のネームスペース(locals()で確認できる空間)に保持される。
  • 一方クラスの場合、aへの参照はsampleクラスのインスタンス変数(つまりself.a)に保持される。

ところだと私は考えます。しかし、私もこの回答をまとめながら「だから何?」と本質的な違いを見出せずにいます。(単純な呼び出し効率だけを考えると関数の方が優位だと思いますな気がする。しかしそれを体系立てて説明できない。。。)深い&示唆にとむ質問だと感心しています。

投稿2021/06/20 03:29

編集2021/06/20 04:15
YouheiSakurai

総合スコア6141

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

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

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
LouiS0616

総合スコア35658

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

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

LouiS0616

2021/06/20 03:23 編集

関数とクラスどちらを使うべきかという議論では、当然セマンティクスの観点も必要です。 しかし私自身オブジェクト指向に精通しているわけではありませんので、それについての回答は避けます(意見が無いわけでは無いですが、言語化できるほど明快な主張ではありません)。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.53%

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

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

質問する

関連した質問