Wiedereinführung in Python-Dekoratoren ~ Lernen wir Dekoratoren nach Typ ~

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.

Zielperson

Gut zu wissen

Klassifizierung der Dekorationsfunktionen

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?)

1. Wenn Sie eine Wrapper-Funktion mit einem Dekorator ohne Argumente zurückgeben

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.

2. Wenn der Dekorator mit Argumenten keine Wrapper-Funktion zurückgibt

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.

3. Wenn Sie eine Wrapper-Funktion mit einem Dekorator mit Argumenten zurückgeben

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.

Mal sehen, was für ein Dekorateur es ist

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.

Lassen Sie uns Dekorateure reibungslos montieren können

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

Wiedereinführung in Python-Dekoratoren ~ Lernen wir Dekoratoren nach Typ ~
Trainieren! !! Einführung in Python Type (Type Hints)
Lerne Python durch Zeichnen (Turtle Graphics)
Einfaches Erlernen von Python beim Schreiben
[Einführung in die Udemy Python3 + -Anwendung] 28. Kollektiver Typ
Antwort auf AtCoder Beginners Selection von Python3
[Einführung in die Udemy Python3 + -Anwendung] 21. Taple-Typ
Funktion zum Speichern von Bildern nach Datum [python3]
[Einführung in die Udemy Python3 + -Anwendung] 24. Wörterbuchtyp
Empfohlene Bücher von 3 Typen im Zusammenhang mit Python
[Einführung in die Udemy Python3 + -Anwendung] 16. Listentyp
Möchten Sie Python-Dekoratoren Typhinweise hinzufügen?
[Python] So zeigen Sie die Elemente der Liste nebeneinander an
Auf Python 2.7.9 aktualisiert
[Python] Verwendung von zwei Arten von type ()
Wiedereinführung in Docker
Numerischer Python-Typ
So löschen Sie die von Python ausgegebenen Zeichen
Über Python Decorator
So erhalten Sie Elemente vom Typ Wörterbuch von Python 2.7
Python2-Zeichenfolgentyp
[Python] So sortieren Sie Instanzen nach Instanzvariablen
Ich möchte die Produkte verkaufen, die ich durch Python Scraping Mercari aufgelistet habe
Python # String-Typ
Über Python-Dekorateure
Wie man mit dem Datum / Uhrzeit-Typ in Pythons SQLite3 umgeht
Führen Sie Power Query aus, indem Sie Argumente an Python übergeben
[Python] Fortsetzung - Konvertieren Sie PDF-Text Seite für Seite in CSV
"Backport" zu Python 2
Lerne Python-Gesten
[Keras] Persönliches Memo zum Klassifizieren von Bildern nach Ordner [Python]
So konvertieren Sie den Python # -Typ für Super-Anfänger von Python: str
Liste der Beiträge zur Optimierung durch Python to Docker
[Wiedereinführung in Python] Importieren über das übergeordnete Verzeichnis
So schreiben Sie einen Listen- / Wörterbuchtyp von Python3
[Python] Konvertiert PDF-Text für jede Seite in CSV (2/24 Postscript)
Lesen Sie die XML-Datei anhand des Python-Tutorials
Python - Hinweise beim Konvertieren vom Typ str in den Typ int
So speichern Sie eine von Python gekratzte Tabelle in CSV
Python # So überprüfen Sie Typ und Typ für Super-Anfänger
Konvertieren Sie den Webpay-Entitätstyp in den Dict-Typ (rekursiv in Python).
Lernen Sie die asynchrone Verarbeitung / Collouts von Python im Vergleich zu Node.js
Python> Datum / Uhrzeit> Von der Datumszeichenfolge (ISO-Format: 2015-12-09 12:40:08) zum Datum / Uhrzeit-Typ
Primzahlbeurteilung durch Python
So installieren Sie Python
Lerne Python mit ChemTHEATER
Visualisierungsnotiz von Python
Kommunikationsverarbeitung durch Python
Änderungen von Python 3.0 zu Python 3.5
Änderungen von Python 2 zu Python 3.0
Schreiben Sie Python2-Code in Python3 um (2to3)
So installieren Sie Python
Einführung in die Python-Sprache
Einführung in OpenCV (Python) - (2)
Beachten Sie, dass Python ein Daemon ist
Einführung von Python 2.7 in CentOS 6.6
Beamformer-Antwort von Python