2013-10-21 11 views
8

で__call__私はPythonのデコレータを理解しようとしていたと私はこの1つに同等のプログラムを書くためにしようとしていた。Pythonのデコレータ - クラス

class myDecorator(object): 
    def __init__(self, f): 
     print ("inside myDecorator.__init__()") 
     f() # Prove that function definition has completed 

    def __call__(self): 
     print ("inside myDecorator.__call__()") 

@myDecorator 
def aFunction(): 
    print ("inside aFunction()") 

print ("Finished decorating aFunction()") 

aFunction() 

問題は、私はクラスの__call__方法がどのように理解していないのですです最後にaFunction()を呼び出すことによって呼び出されます。

aFunction()myDecorator.__call__(aFunction)に置き換えられます。 私を助けてもらえますか?デコレータのない同等のプログラムはどのようになりますか?

ありがとうございます!

答えて

8

あなたのコードの出力は

inside myDecorator.__init__() 
inside aFunction() 
Finished decorating aFunction() 
inside myDecorator.__call__() 

まずで、あなたはこの@デコレータ構文は何を意味し、知っているのですか?

@decorator 
def function(a): 
    pass 

というのがもうひとつの方法である:

@myDecorator 
def aFunction(): 
    print ("inside aFunction()") 

は、最初はただ

def aFunction(): 
    print ("inside aFunction()") 
aFunction = myDecorator(aFunction) 

を意味あなたの場合、あなたは基本的に新しいを作成し、

def function(a): 
    pass 
function = decorator(function) 

をので、 myDecoratorクラスのインスタンス。それはコンストラクタ(__init__)であり、aFunction関数オブジェクトに渡します。そして、printと指定された関数を実行します。また、関数がインタプリタによって読み込まれているときに実行されているのではなく、このファイルから何かをインポートする場合には、 が実行され、使用や呼び出しではありません。

次に、aFunctionが依然としてmyDecoratorインスタンスを参照しているときにaFunction()を実行し、実行するmyDecoratorの__call__メソッドを呼び出すようにします。 f()は、__call__メソッドが定義されている場合、簡略化のためにオブジェクトが呼び出されるように、デフォルトオブジェクトの呼び出し動作を有効にしてオーバーライドするために使用されるため、この場合はf.__call__(f)と同じ意味です。

呼び出されたときにaFunctionを実行する場合は、インスタンス変数に__init__を割り当て、myDecoratorの__call__で呼び出す必要があります。

1

afunctionは、クラスmyDecoratorのインスタンスに置き換えられています。クラスは__call__メソッドを持っているので、インスタンスは関数のように呼び出すことができます。したがって、その署名が互換性があると仮定すると(通常、デコレータは*args**kwargsを使用するものを返します)、インスタンスは元の関数の代わりに使用できます。

通常、__call__メソッドはラップされた関数を呼び出します。 __init__で行うのは一般的に間違っています。 __init__は、ラップされた関数への参照をインスタンス属性として格納し、__call__が呼び出せるようにする必要があります。

1

これは、デコレータの全目的です。つまり、デコレータによって返された関数を関数に置き換える(または、通常はラップする)ことです。あなたのケースでは、aFunctionmyDecoratorのインスタンスに置き換えられているので、aFunction()を呼び出すと、実際にそのインスタンスが呼び出されます。そしてPythonでは、クラスインスタンスを呼び出すと__call__メソッドが呼び出されます。装飾された機能を定義する

このとまったく同じです:

def aFunction(): 
    print("inside aFunction()") 
aFunction = myDecorator(aFunction) 

通常、当然のことながら、ラッピング機能は、それがないものは何でもやった後、元の関数を呼び出します。

1

は、ここで修正です:

class myDecorator(object): 
    def __init__(self, f): 
     print ("inside myDecorator.__init__()") 
     self.f = f #Store the function being wrapped 

    def __call__(self): 
     print ("inside myDecorator.__call__()") 
     self.f() # Call the wrapped function 
+0

関数のargsを受け入れるにはdef __call __(self、* args、** kwargs):をfに渡します – theannouncer

関連する問題