Notez que les décorateurs Python doivent avoir des wraps

Les décorateurs Python sont difficiles à comprendre au début. Et même si vous pensez le comprendre, ce n'est souvent pas la mise en œuvre des meilleures pratiques. En attendant, qu'est-ce que "functools.wraps" que je ne connaissais pas jusqu'à présent?

Documentation officielle

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

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

Ceci est une mise à jour lors de la définition d'une fonction wrapper_wrapper()Est une fonction pratique qui appelle comme décorateur de fonction.
C'est partiel(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)Est équivalent à

Why? Si tu regardes ça, c'est un gâchis, mais ** Les noms de fonctions et les Docstrings deviendront des décorateurs ** Je me demande si cela signifie

En fait, voir le mouvement

Code de test

def hoge_decorator(f):
    def hoge_wrapper(*args, **kwargs):
        """C'est le décorateur Docstring"""
        print("C'est un décorateur")
        return f(*args, **kwargs)
    return hoge_wrapper

@hoge_decorator
def hoge_function():
    """C'est une fonction décorée Docstring"""
    print("C'est la fonction décorée!")

if __name__ == '__main__':
    hoge_function()

résultat

C'est un décorateur
C'est la fonction décorée!

Celui que vous voyez souvent. Il n'y a pas de problème particulier avec le mouvement.

Mais ...


def hoge_decorator(f):
    def hoge_wrapper(*args, **kwargs):
        """C'est le décorateur Docstring"""
        print("C'est un décorateur")
        return f(*args, **kwargs)
    return hoge_wrapper

@hoge_decorator
def hoge_function():
    """C'est une fonction décorée Docstring"""
    print("C'est la fonction décorée!")

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

résultat

C'est un décorateur
C'est la fonction décorée!
hoge_wrapper
C'est le décorateur Docstring

Cette? C'est drôle, non? L'attribut caché sorti par print est un décorateur.

Le problème avec ceci est que le doctest ne fonctionne pas. (Je pense qu'il y a beaucoup de gens unittest ...) En outre, le fonctionnement normal peut ne pas être un problème, mais le nom n'est pas réellement le nom de la fonction en cours d'exécution. Je ne sais pas de quoi vous parlez, mais ... c'est un développement.

functools.wraps

Donc C'est là que ** functools.wraps ** entre en jeu. Utilisons-le immédiatement.

import functools

def hoge_decorator(f):
    @functools.wraps(f)
    def hoge_wrapper(*args, **kwargs):
        """C'est le décorateur Docstring"""
        print("C'est un décorateur")
        return f(*args, **kwargs)
    return hoge_wrapper

@hoge_decorator
def hoge_function():
    """C'est une fonction décorée Docstring"""
    print("C'est la fonction décorée!")

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

résultat

C'est un décorateur
C'est la fonction décorée!
hoge_function
C'est une fonction décorée Docstring

Ça m'a l'air bien.

doctest

Le dernier est doctest. Au fait, si vous ne testez pas normalement et si vous réussissez le test, il n'y aura pas de journal, alors ajoutez -v comme paramètre. De plus, comme le test du décorateur est également exécuté, le décorateur Docstring a été supprimé.

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):
    """C'est une fonction décorée Docstring
    >>> hoge_function(2)
    4
    """
    return n ** 2
if __name__ == '__main__':
    doctest.testmod()

résultat

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

Après tout, le test n'est pas en cours d'exécution.

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):
    """C'est une fonction décorée Docstring
    >>> hoge_function(2)
    4
    """
    return n ** 2
if __name__ == '__main__':
    doctest.testmod()

résultat

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.

Le test a réussi correctement.

Recommended Posts

Notez que les décorateurs Python doivent avoir des wraps
L'attitude que les programmeurs devraient avoir (Le Zen de Python)
Notez qu'il prend en charge Python 3
[python] Script qui (devrait) mettre à jour pwsh
Remarque: Python
Note de Python
Remarque: décorateur Python
Note de programmation Python
[Python] Note d'apprentissage 1
Note d'apprentissage Python_004
Notez que les spécifications de Pandas loc ont changé.
Note d'apprentissage Python_003
Notez que la notation d'inclusion de liste de Python est toujours déroutante
À propos de Python Decorator
[Remarque] openCV + python
À propos des décorateurs Python
Note du débutant Python
Importez / rechargez dynamiquement les modules qui ont changé dans Python
Notez qu'écrire comme ça avec ruby c'est écrire comme ça avec python
Notation d'inclusion Python3 (liste, dictionnaire) que j'ai vue quelque part
[Note] future déclaration ~ Python ~
[Note] Lecture de fichier ~ Python ~
Remarque pour faire de python un démon
Remarque: python Skeleton Nya
Note d'introduction Python Tkinter
Prise en compte des décorateurs Python du type qui passe des variables
Notez les liens qui peuvent être utiles lors de l'utilisation de Python, Selenium2