それは文脈に大きく依存します。
基本的に、関数がの引数である場合、bar
その関数を実装する方法を知るのは呼び出し元の責任です。bar
気にする必要はありません。しかし、その結果、bar
のドキュメントには、必要な機能の種類を説明する必要があります。
多くの場合、これは非常に適切です。明らかな例はmap
組み込み関数です。map
リスト内の各アイテムに関数を適用し、結果のリストを返すロジックを実装します。map
それ自体は、アイテムが何であるか、または関数がそれらに対して何をしているのかを知りませんし、気にしません。map
のドキュメントには、1つの引数の関数が必要であると記載されている必要があり、の各呼び出し元はmap
、適切な関数を実装または検索する方法を知っている必要があります。しかし、この配置は素晴らしいです。これにより、カスタムオブジェクトのリストと、それらのオブジェクトを具体的に操作する関数を渡すことができ、map
離れてその一般的なことを実行できます。
しかし、多くの場合、この配置は不適切です。関数は、高レベルの操作に名前を付け、内部実装の詳細を非表示にするため、操作を1つの単位と考えることができます。その操作の一部を関数パラメーターとして外部から渡すことを許可すると、その操作がその関数のインターフェースを使用する方法で機能することが明らかになります。
より具体的な(多少工夫されていますが)例が役立つ場合があります。Person
とを表すデータ型を実装し、誰かのフルネームと役職を文字列にフォーマットしたり、クライアントコードを電子メールの署名やレターヘッドなどに挿入したりするためJob
の関数を作成しているとします。name_and_title
明らかにとが必要にPerson
なりJob
ます。呼び出し元が人の名前をフォーマットする方法を決定できるようにするために、関数パラメーターをとる可能性がありますlambda firstname, lastname: lastname + ', ' + firstname
。しかし、これを行うには、私が人々の名前を別々の名と姓で表していることを明らかにすることです。ミドルネームのサポートに変更したい場合は、name_and_title
ミドルネームを含めることができないか、受け入れる関数のタイプを変更する必要があります。名前が4つ以上あることに気づき、名前のリストを格納するように変更することにした場合は、name_and_title
受け入れる関数のタイプを必ず変更する必要があります。
したがって、あなたのbar
例では、どちらが良いかはわかりません。これは、意味のない抽象的な例だからです。それは、toの呼び出しが、実行することになっていることpartialfun
の実装の詳細であるbar
かどうか、またはpartialfun
呼び出しが呼び出し元が知っている(そして何か他のことをしたいと思うかもしれない)ものであるかどうかによって異なります。それが「の一部」である場合bar
、それはパラメータであってはなりません。呼び出し元の「一部」である場合は、パラメーターである必要があります。
膨大な数の関数パラメーターをbar
持つ可能性があることは注目に値します。、、、およびを呼び出します。これらはすべてパラメータ化して、より柔軟にすることができます。sum
map
operator.mul
bar
def bar(fn, xs,ys, g, h, i):
return fn(g(h(i,xs,ys))
そして、g
の出力で呼び出される方法h
も抽象化できます。
def bar(fn, xs, ys, g, h, i, j):
return fn(j(g, h(i, xs, ys)))
そして、bar
何もしなくなるまで続けていくことができます。すべては渡された関数によって制御されます。呼び出し元は、100個の関数を記述して実行するのではなく、実行したいことを直接実行したほうがよいでしょう。そしてそれらをに渡しbar
て関数を実行します。
ですから、常に当てはまる明確な答えはありません。それはあなたが書いている特定のコードに依存します。