pythonパラメータリストのselfは冗長性に等しくない

3383 ワード

pythonパラメータリストのselfは冗長性に等しくない
読み取り:
7回   時間:2011-12-02 05:57:36   フォント:[大きい  中  小]
selfは、グローバル変数/関数とオブジェクト内のメンバー変数/関数を区別するのに役立ちます.例えば、Rubyの@や@@よりずっとはっきりしていると思う役割ドメインメカニズムを提供しています.これは習慣的かもしれませんが、C++、Javaのthisに似ています. 
しかし、selfにはいつも私を困らせるところがあります.私は以前ここで言ったことがあります.Python 3でこれらが改善されることを夢見ていました.それから通常、話題を引き起こし、最終的には人々の言う「隠れている」ことに終わります. 
私はブラジルにいた時、Luciano Ramalho(ブラジルPython組織の議長)と話したことがあります.彼は私にどこにもいないselfが私を困らせているのではなく、パラメータリストのselfであることを理解させ、非pythonic(un-pythonic)とも呼ばれていると思います. 
どのように使用されていますか 
以下に、クラスの使用方法を説明する簡単なPythonコードを示します. 


def f(): pass 
a = 1 
class C1(object): 
a = 2 
def m1(self): 
print a # Prints '1' 
print self.a # Prints '2' 
f() # The global version 
self.m2() # Must scope other members 
def m2(self): pass 
obj = C1() 
obj.m1() 
まず、f()およびaを見て、それらはいずれもグローバル役割ドメインで呼び出すことができる.クラスC 1はobjectから継承されるように定義されています.これは新しいクラスを定義する標準的なプロセスです(Python 3ではこれらがより明らかにならないと思います). 
なお、m 1()およびm 2()の最初のパラメータはselfである.Pythonではselfはキーワードではありません.しかし、従来のselfは、現在のオブジェクトのアドレス、すなわち、オブジェクトのアドレスを表す最初のパラメータである. 
クラス範囲でaを定義することは、オブジェクトの役割ドメインを作成する方法の1つです.aのmethodにself.aに値を割り当て、文を初めて実行するときにこのドメインのメモリ領域を割り当てることもできます.しかし、2つのバージョンのaを区別する必要がある.method内部でaを使用すると、このaはグローバルバージョンであり、self.aはオブジェクトドメインを表しています(クラス内でグローバル変数を割り当てることもできますが、ここでは考慮しません). 
同様に、f()に対する非限定呼び出し(unqualified call)は、self.m 2()を限定することによってメンバー関数(現在のオブジェクトアドレスをm 2()に伝達するself変数として)を呼び出すグローバル関数を形成する. 
パラメータ付きmethodを含むクラスを見てみましょう. 


class C2(object): 
def m2(self, a, b): pass 
このmethodを呼び出すために、オブジェクトインスタンスを作成し、ポイント式を使用してオブジェクトobj上のm 2()を呼び出します. 


obj = C2() 
obj.m2(1,2) 
呼び出し中、objのアドレスはself変数としてm 2()に暗黙的に伝達され、ここではmethodを定義するときに暗黙的に明示的よりよく、methodを呼び出すときに暗黙的にも問題がないという深刻な矛盾に直面した. 
もちろんこれはmethod呼び出し構文に要求される可能性があると思いますが、これはmethodの定義と呼び出しが大きく異なることを意味します.ここでは「明示的」でもpythonicでもありません.パラメータの個数が間違っているmethodを呼び出すと、次のことがわかります. 
obj.m2(1) 
エラーメッセージは次のとおりです. 
Traceback (most recent call last): 
File "classes.py", line 9, in  
obj.m2(1) 
TypeError: m2() takes exactly 3 arguments (2 given) 
method呼び出し中にselfの暗黙的なパラメータが伝達されるため、上記のエラー情報は実際にはmethodをこのように呼び出すべきである. 
C2.m2(obj,1,2) 
上記の文が正常に実行されても、実際の呼び出し方法ではありません.通常のmethod呼び出し構文、すなわち2つのパラメータを渡す必要があります. 
obj.m2(1,2) 
エラーメッセージ「m 2()takes exactly 3 arguments(2 given)」は初心者を混乱させるだけでなく、それを見るたびにぼんやりしています.これはPythonicではなくmethod定義と呼び出しの矛盾を直接指していることを示していると思います. 
絶望的なアドバイス 
長い歴史の中で絶望だらけだが、私はどんなアドバイスがあるのだろうか. 
Python 3.1でselfをキーワードに追加します(少し後ろに互換性がありません)(またはthisを直接使用してC++とJavaプログラマーが移行しやすいようにします).selfに関連する既存のルールはすべて変更されません. 
唯一の変更は、selfをmethodパラメータリストに入れる必要はありません.これは唯一の暗黙的な場所であり、他は明示的であり、依然として変わらないmethod呼び出しを除く. 
method定義と呼び出しの一貫性を実現します.呼び出し時と同じパラメータの個数を持つmethodを定義できます.methodが渡されたパラメータの個数を呼び出すエラーが発生すると、エラーメッセージはmethodに含まれるべき実際のパラメータの個数を通知し、1つ以上ではありません. 
明示vs.冗長 
私がもう一度「隠れているよりも優れている」と聞く前に、あることをはっきりさせることと冗長にすることには違いがあります.私たちはすでにこのような言語を持っています.それはあなたに無数の試練を経験させました.最初はよく見えましたが、その後問題がますます多くなったからです.Javaと呼ばれています. 
すべてのものを明示的にするには、Cまたはアセンブリ、およびマシン内部の動作の詳細を正確に説明し、表示できる他の言語を使用します. 
プログラマーにselfをmethodパラメータリストに強制するのは明示的には関係なく、冗長性を強制するだけで、プログラミングの表現も増えません(methodであることはすでに知っていますが、パラメータリストにselfを追加して注意する必要はありません).それはデッドボードであり、pythonicではないと思います.