11

selfPython がすべての引数リストに明示的なパラメーターを必要とするのはなぜですか?

たとえば、ドキュメントに記載されているクラス Complex で

class Complex: 

    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

    def conjugate(self):
        self.i = -self.i


x = Complex(3.0, -4.5) # 2 instead of 3?
x.conjugate()          # No parameters?

__init__( )最初は、3 つの引数が必要なように見えて、非常に紛らわしいと感じましたが、 Complex( )2 つだけで呼び出します。

selfパラメータが明示的で暗黙的ではない理由は何ですか?

4

4 に答える 4

8

これは、この問題に関するGvRの優れた記事です。self明示的な参照がここにとどまる理由について話します。

彼がとりわけ持ち出すポイント:

の同等性を強化する

foo.meth(arg) == C.meth(foo, arg)

メソッドをクラスに動的にアタッチできるようになり、そのクラスの新しいオブジェクトと既存のオブジェクトの両方から使用できるようになります。

def meth(myself, arg):
   myself.val = arg
   return myself.val

# Poke the method into the class:
C.meth = meth

記事の残りの部分を読むことをお勧めします。とても興味深いです。

于 2012-08-03T12:30:34.787 に答える
2

それがまさにその通りです。Python のオブジェクトは、実際には単なるプロパティ (属性) の袋です。これらの一部は通常の値ですが、その他は関数です。インスタンスの属性であること以外に、クラスへの特別なバインディングはありません。メソッド呼び出しの構文は、最初のパラメーターを渡す面倒を見てくれる、ちょっとした砂糖です。実際、メソッドは単純な関数であり、最初のパラメーターを明示的に渡すことで、そのように呼び出すことができます。

この選択がなされた正確な理由はわかりませんが、無料の関数を属性として既存のオブジェクトに割り当て、それらをメソッドとして呼び出すことができるという事実に関係していると思います。明示的なselfパラメーターがなければ、さらに混乱を招きます。

メカニズムは Javascript に似ていますが、Javascript では、暗黙的に渡されたthis引数が、明示的なパラメーターなしで常に という名前のローカル変数として導入されるのthisに対し、Python では、明示的な最初のパラメーターを使用して、好みの名前を選択できます。selfはキーワードではなく、単なる慣習です。この違いは、関数をより簡単にメソッドとして使用できることも意味します。使用する JavaScript 関数thisは、オブジェクト コンテキストの外で (または、通常はデフォルト オブジェクトのコンテキストでwindow) 使用すると壊れますが、Python では、最初のパラメーターとして適切なオブジェクト。

他の OOP フレーバー (Java、C++ など) もself/thisパラメーターをメソッドに渡しますが、これは暗黙的に行わthisれ、明示的な引数として表示されないことに注意してください。ただし、これらの言語では、メソッドをフリー関数として呼び出すことはできません (vv.、フリー関数をメソッドとして使用することはできません)。

と呼ばれる理由について__init__は、少なくとも 1 つの利点があります。つまり、コンストラクターの名前を変更しなくても、クラスの名前を変更できるということです。これにより、リファクタリングが容易になり、エラーが発生しにくくなります。ところで、これは Python だけではありません。PHP は を使用しています__constructが、クラス名のコンストラクターもサポートされていますが、推奨されていません。

于 2012-08-03T11:49:13.263 に答える
1

(以下は少し単純化しすぎていますが、Pythonオブジェクトの作成がどのように進行するかを理解できるはずです。)

ステートメント

x = Complex(3.0, -4.5)

Complex.__init__直接呼び出すことはありません。むしろ、それは以下と幾分同じです:

x = Complex.__new__(Complex, 3.0, -4.5)
Complex.__init__(x, 3.0, -4.5)

あなたはまだそれが不必要に混乱していると思うかもしれません。しかし、それは最大の柔軟性のためにこのように設計されています。オーバーライド__new__して(通常は基本クラスから継承されるだけです)、クラスのインスタンスを返すよりも多くの(または異なる)ことを行うことができます。ただし、ほとんどの場合、オブジェクトを作成して初期化するためだけに2回の呼び出しを行う必要がないようにするために、型自体を呼び出し可能なオブジェクトとして扱うという省略形に包まれます。 1つのステップでオブジェクトを作成および初期化します。

于 2012-08-03T12:30:25.060 に答える
1

「self」引数について:特定のクラスのインスタンスを識別します。たとえば、C++ では、まったく同じことが行われますが、内部で行われます。

さらに読む: http://linuxgazette.net/issue56/orr.html

于 2012-08-03T11:37:56.807 に答える