Pythonでは、次のことを行うのがより良いスタイルと見なされますか?
- より一般的な、場合によっては内部使用の関数の観点から、有用な関数を明示的に定義します。また、
- 部分機能アプリケーションを使用して、関数カリー化を明示的に記述しますか?
不自然な例として私の質問を説明します。
スコアリング関数とアイテムのリストの2つの引数を取る関数_sort_by_scoringを作成するとします。元のリスト内の各アイテムの位置に基づいてスコアでソートされた元のリストのコピーを返します。2つのスコアリング関数の例も提供されています。
def _sort_by_score(scoring, items_list):
unsorted_scored_list = [(scoring(len(items_list), item_position), item) for item_position, item in enumerate(items_list)]
sorted_list = [item for score, item in sorted(unsorted_scored_list)]
return sorted_list
def _identity_scoring(items_list_size, item_position):
return item_position
def _reversed_scoring(items_list_size, item_position):
return items_list_size - item_position
関数_sort_by_scoreが直接呼び出されることはありません。代わりに、スコアリング関数とその唯一の引数(アイテムのリスト)を_sort_by_scoringに渡し、結果を返す他の単一引数関数によって呼び出されます。
# Explicit function definition style
def identity_ordering(items_list):
return _sort_by_score(_identity_scoring, items_list)
def reversed_ordering(items_list):
return _sort_by_score(_reversed_scoring, items_list)
明らかに、この意図は機能カリー化の観点からよりよく表現されています。
# Curried function definition style
import functools
identity_ordering = functools.partial(_sort_by_score, _identity_scoring)
reversed_ordering = functools.partial(_sort_by_score, _reversed_scoring)
使用法(いずれの場合も):
>>> foo = [1, 2, 3, 4, 5]
>>> identity_ordering(foo)
[1, 2, 3, 4, 5]
>>> reversed_ordering(foo)
[5, 4, 3, 2, 1]
明示的な関数定義スタイルの明らかな利点:
- NameErrorsを発生させることなく、より一般的な関数の前に有用な関数を定義できます。
- ヘルパー関数(スコアリング関数など)は、関数定義本体内で定義できます。
- おそらくデバッグが簡単です。
- 「暗黙的よりも明示的の方が優れている」という理由で、コードは見栄えがします。
カリー化された関数定義スタイルの明らかな利点:
- 関数型プログラミングの意図を慣用的に表現します。
- 簡潔さのおかげで、コードは見栄えがします。
「便利な」機能を定義するために、2つのスタイルのどちらが好ましいですか?より慣用的な/Pythonicなどの他のスタイルはありますか?