私はJava、Ruby、Haskell、Pythonなどの多くの言語にプログラミングしています。自分が取り組んでいるさまざまなプロジェクトのため、1日あたり多くの言語を切り替える必要があります。ここで問題は、Pythonの関数定義の最初のパラメーターが同じオブジェクトのメソッドの呼び出しと同じであるため、self
と書くことを忘れがちです。
そうは言っても、私はこのPythonのアプローチに非常に驚いています。 JavaやRubyのような言語では、現在のオブジェクトの変数を自動的に参照することで物事が簡単になります。 。
私の質問は、なぜこれがself
必要なのかということです。純粋にスタイルの選択ですか、それともPythonでself
を省略できない理由があるのですかJavaおよびC++ letあなたはthis
を省略しますか?
1)メソッドシグネチャの明示的なパラメータとしてself
が必要なのはなぜですか?
メソッドは関数であり、foo.bar(baz)
はbar(foo, baz)
の単なる構文シュガーであるためです。クラスは、一部の値が関数である単なる辞書です。 (コンストラクタも単なる関数なので、Pythonはnew
を必要としないのはそのためです)Pythonは、オブジェクトがより単純なコンポーネントから構築されていることを明示していると言えます。これは、「明示は暗黙よりも優れている」という哲学に基づいています。
対照的に、Javaでは、オブジェクトは実際には魔法であり、言語の単純なコンポーネントに限定することはできません。 Javaでは(少なくともJava 8まで)、関数は常にオブジェクトが所有するメソッドであり、言語の静的な性質のため、この所有権は変更できません。したがって、this
が何を参照するかについては曖昧さがなく、暗黙的に定義することは理にかなっています。
JavaScriptは、Javaのように暗黙的なthis
を持つ言語の例ですが、Pythonのようにオブジェクトとは別に関数を存在させることができます。これは、関数が渡されて異なるコンテキストで呼び出されたときにthis
が何を参照するかについて多くの混乱を引き起こします。多くの人は本能的にthis
が関数のいくつかの組み込みプロパティを参照する必要があると考えていますが、実際には関数の呼び出し方法によって純粋に決定されます。 Pythonのようにthis
を明示的なパラメータとして指定すると、混乱が少なくなると思います。
明示的なself
パラメータのその他の利点:
デコレータは、他の関数をラップする単なる関数です。メソッドは単なる関数なので、デコレータはメソッドに対しても同様に機能します。何らかの暗黙の自己がある場合、デコレータはメソッドに対して透過的に機能しません。
Classmethodsと静的メソッドはインスタンスパラメータを取りません。クラスメソッドは、最初の引数としてclassを取ります(通常、cls
と呼ばれます)。明示的なself
またはcls
パラメーターを使用すると、何が起こっているか、およびメソッド内で何にアクセスできるかがより明確になります。
2)インスタンス変数を常に "_self.
_で修飾する必要があるのはなぜですか?
Javaでは、メンバー変数の前に「_this.
_」を付ける必要はありませんが、Pythonでは常に「_self.
_」が必要です。その理由は、Pythonには変数を宣言するための明示的な構文がないため、_x = 7
_が新しいローカル変数を宣言するか、メンバー変数に割り当てるかを判断する方法がないためです。 _self.
_を指定すると、このあいまいさが解消されます。
クロスサイト複製でAFAIKが実際に触れられていないというかなり単純な理由があります。ここでもPythonは手続き言語として開始されました。これはABCにも基づいていました。手続き型言語。
オブジェクト指向は後で追加され、それが追加されたとき、Guido van Rossumは、Python simple。Pythonにはすでにdict
sと関数があったので、オブジェクトをスロットのdict
に、クラスをdict
of functions?メソッドは、単一の識別された引数をクローズする部分的に適用された関数として解釈できます。そして、それはまさに、メソッドがPythonで実装される方法です:それらはそうではありません。それらは、特別な識別を受ける関数です引数。
上記の回答に基づいて、このトピックについてGuido自身の rambling を読んだ私の結論は次のとおりです。
ビッグアイデア
関数はPython(または唯一のものと言うべきです)の重要な構成要素です。実際、関数を使用してOOPをエミュレートしています。
したがって、クラスは関数の辞書にすぎないため、実行時に任意のクラスに任意の関数をアタッチできます。基本的に、これは実行時に関数を投げる必要があるためです Monkey Patching のようなことができます。ここで、パラメトリック多態性をサポートするself
パラメーター。