2009-03-23 10 views
3

さてさて、私はこの出くわしたとき、私はいくつかのソースを見てみました:パイソン、__init__と自己混乱

>>> def __parse(self, filename): 
...   "parse ID3v1.0 tags from MP3 file" 
...   self.clear() 
...   try: 
...    fsock = open(filename, "rb", 0) 
...    try: 
...     fsock.seek(-128, 2) 
...     tagdata = fsock.read(128) 
...    finally: 
...     fsock.close() 
...    if tagdata[:3] == 'TAG': 
...     for tag, (start, end, parseFunc) in self.tagDataMap.items(): 
...      self[tag] = parseFunc(tagdata[start:end]) 
...   except IOError: 
...    pass 
... 

だから、私はそれをテストすることを決めました。

>>> __parse("blah.mp3") 

そして、私はこのエラーを受け取っ:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: __parse() takes exactly 2 arguments (1 given) 

これは私がこれに遭遇したのは初めてではないでしょう、私は、私は、引数のパラメータリストに自己を含むことを意味しています考え続けますしかし、私はそれが正しいとは限りません。誰かが私に説明しようと思ったのですが、これは私が周りを遊んだりしようとしているコードではなぜそうなるのでしょうか?私はその言葉の理解のレベルのせいで、initやselfが何をするのか、 def x(b):print bはdef x(self、b)と同じです:self.b = b print self.b is not?どうしてそんなに重要なのですか?

私はちょうど基本的な説明をしたいので、私はこれを私の心の中から得ることができます、ありがとう。

答えて

8

def __parseは、いくつかのクラス定義の内側にありました。

メソッドの定義をクラス定義から取り出すことはできません。メソッドの関数定義はクラスの一部です。

def add(a, b): 
    return a + b 

そして

class Adder(object): 
    def __init__(self): 
     self.grand_total = 0 
    def add(self, a, b): 
     self.grand_total += a+b 
     return a+b 

注:この2つの例で

ルック。

  1. この機能にはselfが使用されていません。

  2. クラスメソッドはselfを使用します。通常、他の方法で言う@classmethodのような特定のデコレータを持っていない限り、すべてのインスタンスメソッドはselfを使用します。

  3. この機能は他の機能に依存しません。

  4. クラスメソッドは、クラスAdderのインスタンスによって呼び出されることに依存します。さらに、クラスAdderのインスタンスが正しく初期化されているかどうかによって異なります。この場合、初期化関数(__init__)は、各インスタンスがAdderのインスタンス変数が常にgrand_totalであり、そのインスタンス変数の初期値が0であることを保証しています。

  5. メソッドの機能をAdderクラスから引き出して別に使用することはできません。これはスタンドアロン機能ではありません。 内にと定義されており、その場所のために特定の期待を持っています。クラスです。

+0

ああ、init/selfはクラスで使われていて、defのものではありません。 –

+0

あるいは、def __init__をクラスで使用する必要があります。また、def(self、...)もクラスで使用する必要があります。モジュール/メソッド自体は自己のものではありませんか? –

+1

技術的には、「自己」はキーワードではありません。実際には、あなたはそれがふりをするべきです。 – Brian

0

selfは自動的にクラスのinstancemethodラッパーによって渡されます。この関数はラップされません。それはメソッドではなく、単なる関数です。それはselfパラメータが必要なので、クラスに結びつけなければ意味をなさない。

0

脇に、です。Pythonでクラスの静的メソッドを作成することは可能です。これを行う最も簡単な方法は、デコレータを使用することです(例:@staticmethod)。私はこの種のものは、通常Pythonicの解決策ではないと思う。

2

関数/メソッドは、クラスの外で書かれ、その後Pythonで技術のために使用することができるがをmonkeypatching と呼ばれる:あなたはクラスやオブジェクト指向プログラミングについて少し混乱しているよう

class C(object): 
    def __init__(self): 
    self.foo = 'bar' 

def __output(self): 
    print self.foo 

C.output = __output 
c = C() 
c.output() 
+0

ラウンドアバウト方法のようです。あなたはほんのわずかな例がありますか? – tgray

+0

私はたくさんの例を挙げることができますが、それらはすべて、クラスの属性をそれ以外で定義された関数に設定することに還元されます。 Monkeypatchは、別のライブラリの一部であるか、ソースコードを持たないためにクラス自体を変更できない場合に最も便利です。 –

+0

私は参照してください。説明ありがとう! – tgray

1

が見えます。 '自己'のことは、他のプログラミング言語から来た人々のためのPythonの落とし穴の1つです。 IMO公式チュートリアルではそれをあまりうまく扱いません。 This tutorialはかなり良いようです。

Javaを学んだことがあるなら、selfはpythonでjavaのthisとよく似ています。違いは、Pythonでは、クラス定義内のすべての関数の最初の引数としてselfをリストする必要があるということです。

Pythonが最初のプログラミング言語(または最初のオブジェクト指向言語)である場合、これは簡単な経験則として覚えているでしょう。クラスの一部である関数を定義する場合は、最初の引数としてselfを含めます。クラスの一部ではない関数を定義する場合は、引数にselfを含めないでください。あなたは、クラス関数を取って、余分なコーディングをしなくてもそれをスタンドアロンにすることはできません。最後に、を呼び出して関数を呼び出すときは、引数としてselfを含めないでください。

これらのルールには例外がありますが、今は心配する価値はありません。