Wraps haben eigentlich keinen praktischen Nutzen. Sie werden verwendet, um das Problem der vom Dekorateur verursachten Änderungen in den Eigenschaften der Funktion zu lösen , und zu diesem Zeitpunkt zeigt func nicht auf die tatsächliche Funktion im Dekorator.
Das Quadrat hier zeigt tatsächlich auf Aufrufe von help(square) oder quadrat.__name__ Hör zu.import sys debug_log = sys.stderr def trace(func): if debug_log: def callf(*args, **kwargs): """A wrapper function.""" debug_log.write('Calling function: {}\n'.format(func.__name__)) res = func(*args, **kwargs) debug_log.write('Return value: {}\n'.format(res)) return res return callf else: return func @trace def square(x): """Calculate the square of the given number.""" return x * x
Die dekorierte Funktion von Quadrat ist eigentlich eine andere Funktion (Funktionsattribute wie der Funktionsname ändern sich)
Wenn Sie Wraps zur Dekoration verwenden
Zu diesem Zeitpunkt ändern sich die Attribute des mit Trace dekorierten Quadrats nicht. Sie können helfen,def trace(func): if debug_log: @functools.wraps(func) def callf(*args, **kwargs): """A wrapper function.""" debug_log.write('Calling function: {}\n'.format(func.__name__)) res = func(*args, **kwargs) debug_log.write('Return value: {}\n'.format(res)) return res return callf else: return func
zu sehen. Grund: Wir übersetzen den Wraps-Dekorationscode wie folgt und sein Äquivalent lautet:
Update_wrapper führt eine sehr einfache Aufgabe aus, nämlich einige Attribute (z. B. __name__, __doc__) des durch den umschlossenen Parameter dargestellten Funktionsobjekts (z. B. Quadrat) zu verwenden, um das durch dargestellte Funktionsobjekt zu überschreiben der Parameter-Wrapper (zum Beispiel: callf, hier ruft callf einfach die Quadratfunktion auf, sodass man sagen kann, dass callf eine Wrapper-Funktion von quadrat ist).def trace(func): if debug_log: def _callf(*args, **kwargs): """A wrapper function.""" debug_log.write('Calling function: {}\n'.format(func.__name__)) res = func(*args, **kwargs) debug_log.write('Return value: {}\n'.format(res)) return res callf = functools.update_wrapper(_callf, wrapped = func,assigned = functools.WRAPPER_ASSIGNMENTS,updated = functools.WRAPPER_UPDATES) return callf else: return func
Daher sind in diesem Beispiel nach der Verwendung des Wraps-Dekorators zum „Dekorieren“ von callf die Attribute __doc__, __name__ und andere Attribute von callf völlig dieselben wie die der Funktion „square to be“. Mit Spuren „verziert“.