2013-07-25 8 views
6

コードは、私はこのコードを実行すると、それはどちらかに1,2,3の合計を印刷するのではなく、誰かがこのデコレータコードを私に説明してもらえますか?

class tracer: 
      def __init__(self, func): 
       self.calls = 0 
       self.func = func 
      def __call__(self, *args): 
       self.calls += 1 
       print('call %s to %s' % (self.calls, self.func.__name__)) 
       self.func(*args) 


@tracer 

def spam(a, b, c): 
    print(a + b + c) 

spam(1, 2, 3) 

またマーク・ルッツでの学習のPython第4版から撮影されています本、それはそれが表示されます! 私はこのコード全体を頭で掻き回しています。私はここで何が起こっているのか分かりません。

+0

に*が何*が起こるのでしょうか? – jheld

答えて

7

ここでは、機能の本体が置き換えられています。 spamの元の定義はself.func

class tracer: 
      def __init__(self, func): #tracer(spam), func is assigned spam 
       self.calls = 0 
       self.func = func 

に格納されているtracerクラスのインスタンスを返しtracer(spam)

def spam(...) 
    ... 
spam = tracer(spam) 

、:そう

@tracer 
def spam(...) 
    ... 

等デコレータは、と等価です今すぐspam(実際にはtracerのインスタンス)を呼び出すと、この__call__方法は origianlly spamで定義されたボディをオーバーライドを持っているエッセンスにそう

def __call__(self, *args): 
    self.calls += 1 
    print('call %s to %s' % (self.calls, self.func.__name__)) 

:あなたはtracerクラスで定義され__call__メソッドを呼び出します。ボディは、実行させるには、あなたはそうのようなtracerクラスのインスタンスに格納されている関数を呼び出す必要があります。

def __call__(self, *args): 
       self.calls += 1 
       print('call %s to %s' % (self.calls, self.func.__name__)) 
       self.func(*args) 

結果の

>>> 
call 1 to spam 
6 
+0

すべてのクリスタルクリア今。ありがとう。 :) –

0

*argsで何もしていないのは奇妙です。 __call__の行が欠落している可能性はありますか?

class tracer: 
    def __init__(self, func): 
     self.calls = 0 
     self.func = func 
    def __call__(self, *args): 
     self.calls += 1 
     print('call %s to %s' % (self.calls, self.func.__name__)) 
     return self.func(*args) 
デコレータ構文はこの

def spam(a, b, c): 
    print(a + b + c) 
spam = tracer(spam) 

を言うだけの別の方法ですので、スパムはトレーサークラスのインスタンスなり、spam__init__メソッドに渡され、self.funcに保存されていることを

リコール

スパムが呼び出されると、そのトレーサのインスタンスが呼び出されているので、__call__メソッドが使用されます。

ラッパーは、彼がキーワード引数のためのサポートが含まれていますが、そこではちょうど2つの余分な行があることがわかり、ことを無視していない理由を私は知らない

def __call__(self, *args, **kw): 
    return self.func(*args, **kw) 

ある__call__いつも何もしませんトレーサインスタンスが呼び出されるたびに実行されます。

+0

おっと!申し訳ありませんが、私の間違いは、最後の行を追加するのを忘れていました。それでも、私はこのコードを理解することができません。 –

関連する問題