Hier ist eine Zusammenfassung der Dekorateure, bei denen es sich um Notationen handelt, die das Python-Zeichen (@) verwenden. Es mag schwierig erscheinen, zu dekorieren, aber ich dachte, es wäre eine Abkürzung, um den Typ (das Muster) des Dekorators zu verstehen. Deshalb werde ich diesmal anhand eines einfachen Implementierungsbeispiels des Dekorators für jeden Typ erklären. Überlegen.
Es scheint, dass die Dekorationsfunktion durch die folgenden zwei Faktoren klassifiziert werden kann.
Daher können insgesamt vier Muster aus den Kombinationen berücksichtigt werden. Diesmal werden jedoch drei Muster eingeführt, mit Ausnahme von "Dekoratoren, die keine Argumente verwenden und Wrapper-Funktionen zurückgeben". Der Grund für den Ausschluss ist zu einfach, um einen Sinn zu ergeben.
Als Definition von Begriffen nennen wir die Funktion mit dem Dekorator (die unter @ decorator
definierte Funktion) ** die ursprüngliche Funktion ** (gibt es einen guten Namen?)
def args_logger(f):
def wrapper(*args, **kwargs):
f(*args, **kwargs)
print('args: {}, kwargs: {}'.format(args, kwargs))
return wrapper
@args_logger
def print_message(msg):
print(msg)
#Gleichwertig
'''
def print_message(msg):
print(msg)
print_message = args_logger(print_message)
'''
print_message('hello')
Ausführungsergebnis
hello
args: ('hello',), kwargs: {}
Zuallererst die, die am einfachsten zu verstehen ist. Die Funktion args_logger
gibt eine Wrapper-Funktion zurück, die die Argumentinformationen der ursprünglichen Funktion druckt ().
Mit anderen Worten, die Funktion mit "@ args_logger" spuckt bei jeder Ausführung Argumentinformationen aus.
Wie in diesem Beispiel ist es üblich, die zurückgegebene Wrapper-Funktion "Wrapper" zu nennen.
funcs = []
def appender(*args, **kwargs):
def decorator(f):
#Der Verarbeitungsinhalt kann abhängig vom Inhalt von Args oder Kwargs geändert werden oder nicht.
print(args)
if kwargs.get('option1'):
print('option1 is True')
#Fügen Sie den Funktionen die ursprüngliche Funktion hinzu
funcs.append(f)
return decorator
@appender('arg1', option1=True)
def hoge():
print('hoge')
@appender('arg2', option2=False)
def fuga():
print('fuga')
#Gleichwertig
'''
def hoge():
print('hoge')
appender('arg1', option1=True)(hoge)
def fuga():
print('fuga')
appender('arg2', option2=False)(fuga)
'''
for f in funcs:
f()
Ausführungsergebnis
('arg1',)
option1 is True
('arg2',)
hoge
fuga
Der "Appender" -Dekorator hängt die ursprüngliche Funktion an die Funktionsliste an. Sie können den Verarbeitungsinhalt abhängig von dem an die Dekorationsfunktion übergebenen Argument ändern (ich konnte mir diesmal kein gutes Beispiel vorstellen, also habe ich es nur entsprechend gedruckt).
Beachten Sie, dass Sie die ursprüngliche Funktion f
in der Dekoratorfunktion nicht direkt verarbeiten können, wenn Sie Argumente im Dekorator behalten. Definieren Sie stattdessen eine "Funktion, die die ursprüngliche Funktion verarbeitet". Dieser Funktionsname wird üblicherweise (wahrscheinlich) als "Dekorateur" bezeichnet.
Die Funktion app / Flask.route
von Flask gilt als Dekorateur für dieses Muster.
https://github.com/pallets/flask/blob/3a0ea726bd45280de3eb3042784613a676f68200/flask/app.py#L1222
Es scheint, dass dieses Muster einfach verwendet wird, um eine Rückruffunktion wie eine Flasche zu definieren.
def args_joiner(*dargs, **dkwargs):
def decorator(f):
def wrapper(*args, **kwargs):
newargs = dargs + args #Beitrittsliste
newkwargs = {**kwargs, **dkwargs} #Wörterbücher kombinieren(python3.Funktioniert mit 5 oder höher)
f(*newargs, **newkwargs)
return wrapper
return decorator
@args_joiner('darg', dkwarg=True)
def print_args(*args, **kwargs):
print('args: {}, kwargs: {}'.format(args, kwargs))
#Gleichwertig
'''
def print_args(*args, **kwargs):
print('args: {}, kwargs: {}'.format(args, kwargs))
print_args = args_joiner('darg', dkwarg=True)(print_args)
'''
print_args('arg', kwarg=False)
Ausführungsergebnis
args: ('darg', 'arg'), kwargs: {'kwarg': False, 'dkwarg': True}
Es wurde komplizierter mit dem Gefühl einer Kombination aus erstem und zweitem Beispiel.
Der Dekorator args_joiner
gibt eine Funktion zurück, die ein Argument verwendet, das die Argumente der ursprünglichen Funktion und des Dekorators verkettet (der Prozess der Verkettung der Argumente hat keine tiefe Bedeutung, nur ein Beispiel). Beachten Sie, dass die Verschachtelung einmal tiefer wurde, wenn "das Zurückgeben einer Funktion zurückgegeben wird". Wenn Sie Ihr Bestes tun, um den Prozess zu verfolgen, wissen Sie, was Sie tun.
An drei Beispielen zusammengefasst. Um zu verstehen, was der Dekorateur tut, ist es leicht zu erkennen, um welche Art von Dekorateur es sich handelt.
Zum Beispiel wie im ersten Beispiel
def hoge_deco(func):
def wrapper(...):
...
return wrapper
Wenn es so geschrieben ist, wäre es schön zu wissen, dass der hoge_deco
-Dekorator ** kein Argument ** ist und ** eine Wrapper-Funktion zurückgegeben wird **. Das Bewertungsmaterial ist, dass "func" als Argument von "hoge_deco" verwendet wird und dass die "wrapper" -Funktion definiert ist und am Ende zurückgegeben wird.
Wie das zweite Beispiel
def fuga_deco(*args, **kwargs):
def decorator(f):
# args, kwargs,Mach etwas mit f(Fügen Sie f zu einer Liste usw. hinzu.)
...
return decorator
Wenn Sie auf diese Weise geschrieben haben, stellen Sie sich den fuga_deco
-Dekorator als ** Argument ** -Dekorator vor, der ** keine Wrapper-Funktion ** zurückgibt. Das Beurteilungsmaterial ist, dass etwas anderes als eine Funktion im Argument von "fuga_deco" verwendet wird und eine Funktion mit dem Namen "Dekorateur" definiert wird, die die Funktion "f" als Argument anstelle des Namens "Wrapper" verwendet. Kommt zurück. Beachten Sie, dass der Dekorateur dieses Musters keine Wrapper-Funktion zurückgibt, sodass sich die ursprüngliche Funktion selbst überhaupt nicht ändert.
Wie im dritten Beispiel
def piyo_deco(*dargs, **dkwargs):
def decorator(f):
...
def wrapper(*args, **kwargs):
...
return wrapper
return decorator
Wenn es heißt, ist der Dekorator piyo_deco
** ein Argument ** Dekorator, der eine ** Wrapper-Funktion ** zurückgibt. Ist es in Ordnung, eine Entscheidung zu treffen?
Welche Art von Dekorateur gibt es in diesem Beispiel? Ich kann keinen Moment daran denken, aber ich denke, es gibt einige.
Wenn Sie den Code des Dekorateurs verstehen, ist es einfacher, den Dekorateur selbst zu erstellen. Ich denke, dass Sie dieses Mal fast mit jedem der drei Muster schreiben können. Überlegen Sie sich also zuerst, welches Muster Sie benötigen, und schreiben Sie dann mechanisch "* arg, ** args", "def wrapper" oder "def decorator". Wenn Sie können, können Sie als Dekorateurmeister bezeichnet werden. Ich habe selbst noch nie einen Dekorateur gemacht, aber das Schreiben dieses Artikels war eine gute Bewertung. Ich möchte von nun an Bang Bang dekorieren!
Recommended Posts