Bearbeiten : Für ein tiefgreifendes Verständnis des geistigen Modells von Dekoratoren, schau dir dieses fantastische Pycon-Talk hier an. Die 30 Minuten sind es wert.
Eine Möglichkeit, über Dekoratoren mit Argumenten nachzudenken, ist
@decorator
def foo(*args, **kwargs):
pass
übersetzt zu
foo = decorator(foo)
Wenn der Dekorator Argumente hatte,
@decorator_with_args(arg)
def foo(*args, **kwargs):
pass
übersetzt zu
foo = decorator_with_args(arg)(foo)
decorator_with_args
ist eine Funktion, die ein benutzerdefiniertes Argument akzeptiert und den tatsächlichen Dekorator zurückgibt (der auf die dekorierte Funktion angewendet wird).
Ich benutze einen einfachen Trick mit Partials, um meine Dekoratoren einfach zu machen
from functools import partial
def _pseudo_decor(fun, argument):
def ret_fun(*args, **kwargs):
# hier behandeln, z.B.
print ("Dekoratorargument ist %s" % str(argument))
return fun(*args, **kwargs)
return ret_fun
real_decorator = partial(_pseudo_decor, argument=arg)
@real_decorator
def foo(*args, **kwargs):
pass
Update:
Oben wird foo
zu real_decorator(foo)
Eine Auswirkung des Dekorators einer Funktion ist, dass der Name foo
bei der Deklaration des Dekorators überschrieben wird. foo
wird "überschrieben" durch das, was von real_decorator
zurückgegeben wird. In diesem Fall ein neues Funktionsobjekt.
Alle Metadaten von foo
werden überschrieben, insbesondere die Docstring und der Funktionsname.
>>> print(foo)
.ret_fun at 0x10666a2f0>
functools.wraps gibt uns eine bequeme Methode, um die Docstring und den Namen zur zurückgegebenen Funktion zu "heben".
from functools import partial, wraps
def _pseudo_decor(fun, argument):
# Magische Soße, um den Namen und die Docstring der Funktion hervorzuheben
@wraps(fun)
def ret_fun(*args, **kwargs):
# vor der Funktionsausführung hier, z.B.
print("Dekoratorargument ist %s" % str(argument))
zurückgegebener_wert = fun(*args, **kwargs)
# nach der Ausführung hier, z.B.
print("Zurückgegebener Wert ist %s" % zurückgegebener_wert)
return zurückgegebener_wert
return ret_fun
real_decorator1 = partial(_pseudo_decor, argument="some_arg")
real_decorator2 = partial(_pseudo_decor, argument="some_other_arg")
@real_decorator1
def bar(*args, **kwargs):
pass
>>> print(bar)
>>> bar(1,2,3, k="v", x="z")
Dekoratorargument ist some_arg
Zurückgegebener Wert ist None
5 Stimmen
Dein Beispiel ist nicht syntaktisch korrekt.
execute_complete_reservation
erwartet zwei Parameter, aber du übergibst ihm nur einen. Dekorateure sind nur syntaktischer Zucker, um Funktionen in andere Funktionen einzuschließen. Siehe docs.python.org/reference/compound_stmts.html#function für die vollständige Dokumentation.