PythonのZenは、物事を行う方法は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()を使用できます。
もう少し面白い。私の見解では、関数はある意味では、インターフェースのPythonicバージョンです。
最後に、グイド自身から:
能力/インターフェースについて話すと、「ローグ」の特別なメソッド名のいくつかについて考えさせられました。言語リファレンスでは、「クラスは、特殊な名前でメソッドを定義することにより、特殊な構文(算術演算や添え字やスライスなど)によって呼び出される特定の演算を実装できる」と述べています。しかし、構文のサポートではなく、組み込み関数の利点のために提供されているように見える、
__len__
またはのような特別な名前を持つこれらすべてのメソッドが__unicode__
あります。それはので、おそらく、インターフェイスベースのPythonで、これらの方法は、ABCの定期的な名前のメソッドに変わるでしょう__len__
になるだろうclass container: ... def len(self): raise NotImplemented
それについてもう少し考えますが、すべての構文操作が特定のABCで適切な通常の名前のメソッドを呼び出さ
<
object.lessthan
comparable.lessthan
ないのはなぜかわかりません。「」は、例えば、あろうおそらく呼び出し「(あるいは「」「)。したがって、もう1つの利点は、Pythonをこの複雑な名前の奇妙さから引き離すことができることです。これは、HCIの改善のようです。うーん。同意するかどうかはわかりません(図:-)。
最初に説明したいのが「Pythonの理論的根拠」です。
まず、HCIの理由から、x.len()ではなくlen(x)を選択しました(
def __len__()
かなり後になりました)。実際には2つの理由があり、どちらもHCIです。(a)一部の操作では、接頭表記は単にpostfixよりも読みやすくなります-接頭辞(およびインフィックス!)の操作は数学において長い伝統があり、ビジュアルが問題について数学者が考える助けとなる表記法を好みます。式を次のよう
x*(a+b)
に書き換える簡単さを比較してくださいx*a + x*b
生OO表記を使用して同じことをやっての不器用さにします。(b)何かの長さを要求していること
len(x)
を知っているというコードを読んだとき。これは2つのことを教えてくれます。結果は整数であり、引数はなんらかのコンテナです。逆に、私がを読んだときx.len()
、それがx
インターフェイスを実装しているコンテナ、または標準を持つクラスから継承しているコンテナの一種であることをすでに知っている必要がありますlen()
。マッピングを実装していないクラスにget()
orkeys()
メソッドがある場合、またはファイルではないものにwrite()
ください。同じことを別の言い方をすると、「len」は組み込みの操作と見なされ ます。それを失うのは嫌だ。あなたがそれを意味していたのかどうかははっきりしませんが、 'def len(self):...'は通常の方法に降格したいようです。私はそのことを強く-1としています。
説明することを約束したPythonの理論的根拠の2番目のビットは、
__special__
単に見るだけでなく、 特別な方法を選んだ理由special
です。クラスがオーバーライドする可能性のある多くの操作、一部の標準(__add__
またはまたは__getitem__
)、一部の標準ではない(たとえば、ピクルス__reduce__
は長い間Cコードでまったくサポートされていなかった)を予期していました。これらの特別な操作で通常のメソッド名を使用したくありませんでした。そのため、既存のクラス、またはすべての特別なメソッドのエンサイクロペディックメモリを持たないユーザーが作成したクラスは、実装するつもりのない操作を誤って定義してしまう可能性があります。 、悲惨な結果をもたらす可能性があります。IvanKrstićはこれをより簡潔に彼のメッセージで説明しました。メッセージは私がこれをすべて書いた後に届きました。---Guido van Rossum(ホームページ:http ://www.python.org/~guido/ )
これについての私の理解は、特定のケースでは、プレフィックス表記がより意味をなす(つまり、Duck.quackがquack(Duck)よりも言語の観点から理解できる)ことであり、関数も「インターフェース」を許可します。
そのような場合、私の推測は、Guidoの最初の点のみに基づいてget_king_movesを実装することです。しかし、それでも、同様のプッシュメソッドとポップメソッドを使用してスタッククラスとキュークラスを実装するなど、関数またはメソッドのどちらであるかについて、未解決の問題が数多く残っています。(私は本当にプッシュポップインターフェイスに信号を送りたいので、ここでは関数を推測します)
TLDR:関数とメソッドのどちらを使用するかを決定するための戦略を誰かが説明できるか?
X.frob
もX.__frob__
、独立していても、それほど大きな違いはありませんfrob
。