Warum können Python-Dekoratoren nicht über Definitionen hinweg verkettet werden?

8

Warum sind die folgenden beiden Skripte nicht gleichwertig?

(Aus einer anderen Frage: Python-Dekorierer verstehen )

%Vor%

und mit einem dekorierten Dekorateur:

%Vor%

Warum möchte ich es wissen? Ich habe einen retry decorator geschrieben, um MySQLdb-Exceptions abzufangen - wenn die Exception vorübergehend ist (z. B. Timeout), wird sie die Funktion nach dem Einschlafen erneut aufrufen.

Ich habe auch einen modifies_db Decorator, der sich um einige cache-bezogene Housekeeping kümmert. modifies_db ist mit retry dekoriert, also nahm ich an, dass alle mit modifies_db dekorierten Funktionen auch implizit wiederholen würden. Wo bin ich falsch gelaufen?

    
RobM 19.01.2010, 14:09
quelle

3 Antworten

9

Das Problem mit dem zweiten Beispiel ist das

%Vor%

versucht, makeitalic , den Dekorator, und nicht wrapped , die Funktion, die es zurückgibt, zu dekorieren.

Sie können tun, was ich denke, Sie beabsichtigen mit etwas wie diesem:

%Vor%

Hier verwendet makeitalic makebold , um wrapped zu dekorieren.

    
Will Harris 19.01.2010, 14:50
quelle
1

Der Grund dafür ist, dass wrapped () innerhalb von makebold keine Argumente akzeptiert.

Wenn du den Dekorateur so verwendest, kann das einige Probleme verursachen, ich werde ein Beispiel veröffentlichen, wie du das erreichen kannst, was du willst, aber gib mir nur einen Moment.

Hier ist ein funktionierendes Beispiel für das, was Sie brauchen.

%Vor%

makebold ist irgendwie hässlich, aber es zeigt Ihnen, wie man einen Dekorator schreibt, der optional einen anderen Dekorator umschließen kann.

Hier ist die Ausgabe aus dem obigen Skript:

%Vor%

Beachten Sie, dass makebold der einzige rekursive Dekorator ist. Beachten Sie auch den feinen Unterschied in der Verwendung: @makebold() vs @makeitalic .

    
Bryan McLemore 19.01.2010 14:12
quelle
0

Das Problem ist das Ersetzen von "makeitalic" (welches ein Argument benötigt) durch die "wrapped" -Funktion in "makebold", die keine Argumente benötigt.

Verwenden Sie *args, **kwargs , um Argumente weiter unten in der Kette weiterzugeben:

%Vor%     
truppo 19.01.2010 14:15
quelle

Tags und Links