In diesem Artikel , der aus verschiedenen stackoverflow-Fragen mehrfach verlinkt ist, wird beschrieben, wie Dekoratoren aussehen mit Argumenten sind syntaktisch verschieden von denen ohne Argumente.
__init__()
die einzige Methode ist, die zum Ausführen der Dekoration aufgerufen wird, und __call__()
wird jedes Mal aufgerufen, wenn Sie die dekorierte sayHello()
aufrufen." __call__()
auf, das nur ein einziges Argument (das Funktionsobjekt) annehmen kann und das dekorierte Funktionsobjekt zurückgeben muss, das das Original ersetzt __call__()
wird jetzt nur einmal während der Dekoration aufgerufen, und danach wird die dekorierte Funktion, die Sie von __call__()
zurückgeben, für die tatsächlichen Aufrufe verwendet. "Die Erklärung in dem Artikel sagt mir nicht, warum die Sprache so eingerichtet ist:
Obwohl dieses Verhalten sinnvoll ist - der Konstruktor wird jetzt verwendet, um die Decorator-Argumente zu erfassen, aber das Objekt
__call__()
kann nicht mehr als dekorierter Funktionsaufruf verwendet werden, also müssen Sie stattdessen__call__()
verwenden, um die Dekoration auszuführen - Es ist dennoch überraschend, wenn Sie es das erste Mal sehen.
Es gibt zwei verwandte Funktionen dieses Setups, die für mich unangenehm sind:
__init__
und __call__
in beiden, aber haben sie unterschiedliche Bedeutungen? __call__
im Fall von Dekoratoren mit Argumenten zu einem anderen Zweck als dem Aufruf der verzierten Funktion verwenden (wie der Name schon sagt, zumindest aus dem Fall ohne Argumente)? Da __call__
nur direkt nach __init__
aufgerufen wird, übergibt man einfach die Funktion, die als Argument zu dekorieren ist, an __init__
und behandelt alles, was in __call__
in __init__
stattdessen geschehen würde? Es liegt daran, dass in beiden Fällen das Decorator-Objekt aufgerufen wird. Um es klarer zu machen:
%Vor%das:
%Vor%entspricht dem:
%Vor%Was im Fall ohne Argumente passiert, ist, dass der Dekorator direkt aufgerufen wird, anstatt eine Funktion zurückgeben zu müssen, die das zu dekorierende Objekt als Parameter akzeptiert.