Warum unterscheiden sich Python-Dekoratoren mit syntaktischen Argumenten von denen ohne?

8

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.

  • Dekoratoren ohne Argumente: "Beachten Sie, dass __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."
  • Dekoratoren mit Argumenten: "Jetzt ruft der Prozess der Dekoration den Konstruktor auf und ruft dann sofort __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:

  1. Warum bieten wir eine Möglichkeit, Dekoratoren ohne Argumente zu erstellen, die nicht nur ein Sonderfall der allgemeineren Methode zum Spezifizieren von Dekoratoren sind? Und warum benutzen Sie __init__ und __call__ in beiden, aber haben sie unterschiedliche Bedeutungen?
  2. Warum __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?
kuzzooroo 27.11.2013, 05:22
quelle

1 Antwort

9

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.

    
Benno 27.11.2013, 05:31
quelle