Beachten Sie, dass Python-Dekoratoren Wraps haben sollten

Python-Dekorateure sind zunächst schwer zu verstehen. Und selbst wenn Sie glauben, es zu verstehen, ist es oft nicht die Best-Practice-Implementierung. Was ist "functools.wraps", das ich bis jetzt nicht kannte?

Offizielle Dokumentation

https://docs.python.jp/3/library/functools.html#functools.wraps

@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)(Original)

Dies ist eine Aktualisierung beim Definieren einer Wrapper-Funktion_wrapper()Ist eine Komfortfunktion, die als Funktionsdekorateur aufgerufen wird.
Das ist teilweise(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)Ist äquivalent zu

Why? Wenn Sie sich das ansehen, ist es ein Chaos, aber ** Funktionsnamen und Docstrings werden zu Dekoratoren ** Ich frage mich, ob das bedeutet

Eigentlich die Bewegung sehen

Testcode

def hoge_decorator(f):
    def hoge_wrapper(*args, **kwargs):
        """Es ist der Dekorateur Docstring"""
        print("Es ist ein Dekorateur")
        return f(*args, **kwargs)
    return hoge_wrapper

@hoge_decorator
def hoge_function():
    """Es ist eine dekorierte Funktion Docstring"""
    print("Dies ist die dekorierte Funktion!")

if __name__ == '__main__':
    hoge_function()

Ergebnis

Es ist ein Dekorateur
Dies ist die dekorierte Funktion!

Die, die du oft siehst. Es gibt kein besonderes Problem mit der Bewegung.

Aber ...


def hoge_decorator(f):
    def hoge_wrapper(*args, **kwargs):
        """Es ist der Dekorateur Docstring"""
        print("Es ist ein Dekorateur")
        return f(*args, **kwargs)
    return hoge_wrapper

@hoge_decorator
def hoge_function():
    """Es ist eine dekorierte Funktion Docstring"""
    print("Dies ist die dekorierte Funktion!")

if __name__ == '__main__':
    hoge_function()
    print(hoge_function.__name__)
    print(hoge_function.__doc__)

Ergebnis

Es ist ein Dekorateur
Dies ist die dekorierte Funktion!
hoge_wrapper
Es ist der Dekorateur Docstring

Das? Es ist lustig, nicht wahr? Das versteckte Attribut, das von print ausgegeben wird, ist ein Dekorateur.

Das Problem dabei ist, dass doctest nicht funktioniert. (Ich denke, es gibt viele unittest Leute ...) Außerdem ist der normale Betrieb möglicherweise kein Problem, aber der Name ist nicht der Name der Funktion, die ausgeführt wird. Ich weiß nicht, wovon du sprichst, aber ... es ist eine Entwicklung.

functools.wraps

Deshalb Hier kommt ** functools.wraps ** ins Spiel. Lass es uns sofort benutzen.

import functools

def hoge_decorator(f):
    @functools.wraps(f)
    def hoge_wrapper(*args, **kwargs):
        """Es ist der Dekorateur Docstring"""
        print("Es ist ein Dekorateur")
        return f(*args, **kwargs)
    return hoge_wrapper

@hoge_decorator
def hoge_function():
    """Es ist eine dekorierte Funktion Docstring"""
    print("Dies ist die dekorierte Funktion!")

if __name__ == '__main__':
    hoge_function()
    print(hoge_function.__name__)
    print(hoge_function.__doc__)

Ergebnis

Es ist ein Dekorateur
Dies ist die dekorierte Funktion!
hoge_function
Es ist eine dekorierte Funktion Docstring

Hört sich gut an.

doctest

Das letzte ist doktest. Übrigens, wenn Sie normalerweise nicht testen und den Test bestehen, gibt es kein Protokoll. Fügen Sie daher "-v" als Parameter hinzu. Da auch der Dekoratortest ausgeführt wird, wurde der Dekorations-Docstring gelöscht.

import functools
import doctest

def hoge_decorator(f):
    def hoge_wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    return hoge_wrapper

@hoge_decorator
def hoge_function(n):
    """Es ist eine dekorierte Funktion Docstring
    >>> hoge_function(2)
    4
    """
    return n ** 2
if __name__ == '__main__':
    doctest.testmod()

Ergebnis

3 items had no tests:
    __main__
    __main__.hoge_decorator
    __main__.hoge_function
0 tests in 3 items.
0 passed and 0 failed.
Test passed.

Immerhin läuft der Test nicht.

import functools
import doctest

def hoge_decorator(f):
    @functools.wraps(f)
    def hoge_wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    return hoge_wrapper

@hoge_decorator
def hoge_function(n):
    """Es ist eine dekorierte Funktion Docstring
    >>> hoge_function(2)
    4
    """
    return n ** 2
if __name__ == '__main__':
    doctest.testmod()

Ergebnis

Trying:
    hoge_function(2)
Expecting:
    4
ok
2 items had no tests:
    __main__
    __main__.hoge_decorator
1 items passed all tests:
   1 tests in __main__.hoge_function
1 tests in 3 items.
1 passed and 0 failed.
Test passed.

Der Test wurde ordnungsgemäß bestanden.

Recommended Posts

Beachten Sie, dass Python-Dekoratoren Wraps haben sollten
Die Einstellung, die Programmierer haben sollten (The Zen of Python)
Beachten Sie, dass es Python 3 unterstützt
[Python] Skript, das pwsh aktualisiert (sollte)
Hinweis: Python
Python-Notiz
Hinweis: Python-Dekorator
Python-Programmierhinweis
[Python] Lernnotiz 1
Python lernen note_004
Beachten Sie, dass sich die Spezifikationen von Pandas loc geändert haben.
Python lernen note_003
Beachten Sie, dass die Listeneinschlussnotation von Python immer verwirrend ist
Über Python Decorator
[Hinweis] openCV + Python
Über Python-Dekorateure
Python-Anfängernotiz
Importieren / laden Sie Module, die sich in Python geändert haben, dynamisch
Beachten Sie, dass das Schreiben mit Ruby so ist wie das Schreiben mit Python
Python3-Einschlussnotation (Liste, Wörterbuch), die ich irgendwo gesehen habe
[Anmerkung] zukünftige Aussage ~ Python ~
[Hinweis] Datei lesen ~ Python ~
Beachten Sie, dass Python ein Daemon ist
Hinweis: Python Skeleton Nya
Python Tkinter Primer Hinweis
Berücksichtigung von Python-Dekoratoren des Typs, der Variablen übergibt
Beachten Sie Links, die bei der Verwendung von Python, Selenium2 hilfreich sein können