2013-10-21 13 views
8

Ich habe versucht, Python Dekorateure zu verstehen, und ich versuche, ein gleichwertiges Programm zu schreiben ein:Python Dekorateure - __call__ in Klasse

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() 

Das Problem ist, ich nicht verstehen, wie die __call__ Methode der Klasse ist aufgerufen werden, indem am Ende aFunction() aufgerufen wird.

Wird aFunction() durch myDecorator.__call__(aFunction) ersetzt. Können Sie mir bitte helfen? Wie wäre ein gleichwertiges Programm ohne Dekorateure?

Danke!

Antwort

8

Der Ausgang des Codes

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

Zuerst ist, wissen Sie, was das @ Dekorateur Syntax bedeuten?

@decorator 
def function(a): 
    pass 

ist nur eine andere Art zu sagen:

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

in Ihrem Fall also

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

bedeutet nur

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

Zunächst erstellen Sie im Grunde eine neue Instanz der myDecorator-Klasse, aufrufend Es ist Konstruktor (__init__) und übergibt ihm ein aFunction-Funktionsobjekt. Dann führt es Druck und gegebene Funktion aus.Beachten Sie auch, dass dies geschieht, während die Funktion vom Interpreter geladen wird, nicht wenn sie ausgeführt wird. Wenn Sie also etwas aus dieser Datei importieren, wird sie ausgeführt, nicht verwendet oder aufgerufen.

Wenn dann die Funktion aFunction() ausgeführt wird, wenn aFunction immer noch auf die myDecorator-Instanz verweist, wird die __call__-Methode von myDecorator aufgerufen, die ausgeführt wird. Beachten Sie, dass f() in diesem Fall dasselbe ist wie f.__call__(f), da die Methode __call__ verwendet wird, um das Aufrufverhalten des Standardobjekts zu aktivieren und zu überschreiben (zur Vereinfachung kann jedes Objekt aufgerufen werden, wenn die Methode __call__ definiert ist).

Wenn Sie eine Funktion ausführen möchten, wenn sie aufgerufen wird, sollten Sie sie der Instanzvariablen in __init__ zuweisen und sie in __call__ von myDecorator aufrufen.

1

afunction wird durch eine Instanz der Klasse myDecorator ersetzt. Die Klasse hat eine __call__ Methode, so dass die Instanz wie eine Funktion aufgerufen werden kann. Unter der Annahme, dass seine Signatur kompatibel ist (normalerweise gibt ein Dekorator etwas zurück, das *args und **kwargs verwendet), kann die Instanz als Ersatz für die ursprüngliche Funktion verwendet werden.

Normalerweise würde die __call__ Methode die verpackte Funktion aufrufen. In __init__ zu tun ist im Allgemeinen falsch; __init__ sollte einen Verweis auf die umbrochene Funktion als Instanzattribut speichern, damit __call__ es aufrufen kann.

1

Das ist der ganze Zweck eines Dekorators: eine Funktion durch die vom Dekorateur zurückgegebene Funktion zu ersetzen (oder, noch üblicher, zu umbrechen). In Ihrem Fall wird aFunction durch eine Instanz von myDecorator ersetzt. Wenn Sie also aFunction() aufrufen, rufen Sie diese Instanz wirklich auf: In Python ruft der Aufruf einer Klasseninstanz die Methode __call__ auf.

eine eingerichtete Funktion zu definieren, ist genau entspricht dies:

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

Normalerweise würde natürlich die Verpackungsfunktion die ursprüngliche Funktion aufrufen, nachdem tun, was es tut.

1

Hier ist ein fix:

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

um die args der Funktion zu akzeptieren, benutze def __call __ (selbst, * args, ** kwargs): und übergebe sie an f – theannouncer

Verwandte Themen