Pythonでは、メソッドの代わりに関数を使用する必要があるのはいつですか?

| | | | | | | | |

Zen of Pythonは、物事を行う方法は1つしかないと述べていますが、関数を使用する場合とメソッドを使用する場合のどちらを使用するかを決定するという問題に遭遇することがよくあります。

ささいな例-ChessBoardオブジェクトを見てみましょう。ボード上ですべての合法的なキングの動きを利用できるようにするための何らかの方法が必要だとしましょう。 ChessBoard.get_king_moves()またはget_king_moves(chess_board)を記述しますか?

私が調べた関連する質問は次のとおりです。

得られた答えはほとんど決定的ではありませんでした:

Pythonが一部の機能(例:list.index())にメソッドを使用し、他の機能(例:len(list))に関数を使用するのはなぜですか?

主な理由は履歴です。関数は、タイプのグループに対して一般的であり、メソッドをまったく持たないオブジェクト(タプルなど)でも機能することを目的とした操作に使用されました。 Pythonの機能機能(map()、apply()など)を使用するときに、オブジェクトのアモルファスコレクションに簡単に適用できる関数があると便利です。

実際には、組み込み関数としてのlen()、max()、min()は、実際には、各タイプのメソッドとして実装するよりもコードが少なくなります。個々のケースについて疑問を呈することはできますが、それはPythonの一部であり、今ではそのような根本的な変更を行うには遅すぎます。大量のコードの破損を回避するために、関数を残しておく必要があります。

興味深いことですが、上記では、採用する戦略についてはあまり説明していません。

これが理由の1つです-カスタムメソッドを使用すると、開発者はgetLength()、length()、getlength()などの別のメソッド名を自由に選択できます。Pythonは、共通関数len()ができるように、厳密な命名を強制します。

もう少し興味深いです。私の考えでは、関数はある意味でPythonバージョンのインターフェイスです。

最後に、 Guido自身から

< em> Abilities / Interfacesについて話すと、「不正な」特別なメソッド名のいくつかについて考えるようになりました。言語リファレンスでは、「クラスは、特別な構文によって呼び出される特定の操作(算術演算や添え字など)を実装できます。とスライス)特別な名前でメソッドを定義することによって。」しかし、組み込み関数の利益のために提供されているように見える __ len ____unicode __などの特別な名前を持つこれらのメソッドはすべてあります。構文のサポートではなく。おそらくインターフェースベースのPythonでは、これらのメソッドはABCで通常の名前のメソッドに変わるため、 __ len __

クラスコンテナになります。 ... def len(self):Raise NotImplemented  

でも、もう少し考えてみると、すべての構文操作がなぜそうならないのかわかりません 「特定のABCで適切な通常の名前のメソッドを呼び出すだけではありません。たとえば、「&lt; 」は、おそらく「 object.lessthan 」(または「 comparable.lessthan 」)を呼び出します。したがって、もう1つの利点は、Pythonをこの壊れた名前の奇妙さから引き離すことができることです。これは、HCIの改善のように思えます。

うーん。同意するかどうかはわかりません(図:-)。

最初に説明したい「Pythonの理論的根拠」が2つあります。

まず、 HCIの理由からx.len()ではなくlen(x)を選択しました( def __len __()はずっと後になりました)。実際には、2つの絡み合った理由があります。どちらもHCIです。

(a)一部の操作では、接頭辞表記は後置よりも読みやすくなります。接頭辞(および挿入!)操作は、数学において長い伝統があり、ビジュアルは、数学者が問題について考えるのに役立ちます。 x *(a + b)のような式をx * a + x * b に書き直す簡単な方法と、生の方法で同じことを行うという不器用さを比較してください。 OO表記。

(b) len(x)というコードを読んだとき、何かの長さを要求していることを知っています。これは私に2つのことを教えてくれます:結果は整数であり、引数はある種のコンテナです。それどころか、 x.len()を読んだとき、 x は、インターフェイスを実装したり、標準のlen()。マッピングを実装していないクラスにget()またはkeys()メソッドがある場合、またはファイルではないものに write()メソッド。

同じことを別の言い方をすると、「len」は組み込みの操作と見なされます。それを失います。それを意味するかどうかは定かではありませんが、「def len(self):...」は確かに通常のメソッドに降格したいようです。私はその点で強く-1です。

説明することを約束したPythonの理論的根拠の2番目のビットは、単に special ではなく、 __ special __に見える特別なメソッドを選択した理由です。私は、クラスがオーバーライドしたい多くの操作、いくつかの標準(例: __ add __または__getitem __ )、いくつかはそれほど標準的ではない(例:pickle "s __ reduce__ <)を予想していました。 / code>は長い間、Cコードをまったくサポートしていませんでした。既存のクラス、またはすべての百科事典メモリを持たないユーザーによって作成されたクラスのため、これらの特別な操作で通常のメソッド名を使用することは望ましくありませんでした。特別なメソッドは、実装するつもりのない操作を誤って定義する可能性があり、悲惨な結果を招く可能性があります。IvanKrstiƒáは、これをすべて書き留めた後に届いたメッセージで、これをより簡潔に説明しました。

--- Guido van Rossum(ホームページ: http://www.python.org/~guido/

これについての私の理解では、場合によっては、プレフィックス表記の方が理にかなっています(つまり、言語の観点からは、Duck.quackの方がquack(Duck)よりも理にかなっています)。 。) そしてまた、関数は「インターフェース」を可能にします。

そのような場合、私の推測では、Guidoの最初のポイントのみに基づいてget_king_movesを実装します。しかし、それでも、同様のプッシュメソッドとポップメソッドを使用してスタッククラスとキュークラスを実装するなど、多くの未解決の問題が残っています。これらは関数またはメソッドである必要がありますか? (ここでは、プッシュポップインターフェイスに信号を送りたいので、関数を推測します)

TLDR:関数とメソッドをいつ使用するかを決定するための戦略を誰かが説明できますか?