Comment créer un wrapper qui préserve la signature de la fonction à envelopper

Surtout dans les décorateurs de fonction, vous créez et retournez souvent une fonction qui encapsule la fonction de modification que vous recevez en tant qu'argument, mais parfois vous voulez que la signature de la fonction d'encapsulation soit la même que la fonction encapsulée. Dans Python 3.4 et versions ultérieures, cette implémentation est possible en utilisant un décorateur appelé wraps fourni par les functools de la bibliothèque standard.

Dans l'exemple ci-dessous, la fonction funny_function modifiée avec le décorateur ʻargs_as_ints (c'est-à-dire le wrapper modifié avec functools.wraps) a la même signature que la fonction modifiéefunny_function, mais tous Convertissez l'argument en ʻint et faites le même calcul pour la fonction d'origine.

python


# Source: https://stackoverflow.com/questions/147816/preserving-signatures-of-decorated-functions

import functools

def args_as_ints(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        args = [int(x) for x in args]
        kwargs = dict((k, int(v)) for k, v in kwargs.items())
        return func(*args, **kwargs)
    return wrapper

@args_as_ints
def funny_function(x, y, z=3):
    """Computes x*y + 2*z"""
    return x*y + 2*z

Après avoir été qualifié, la fonction funny_function a un membre appelé __wrapped__, qui conserve la fonction d'origine.

Pour inspecter la signature d'une fonction, utilisez la bibliothèque standard inspect. Vous pouvez utiliser la fonction signature fournie par inspect pour récupérer la signature de la fonction en tant qu'objetSignature. Le code suivant garantit que la signature funny_function est la même avant et après la modification.

python


>>> from inspect import signature
>>> str(signature(funny_function))
'(x, y, z=3)'
>>> signature(funny_function) == signature(funny_function.__wrapped__)
True

Recommended Posts

Comment créer un wrapper qui préserve la signature de la fonction à envelopper
Créez une fonction pour obtenir le contenu de la base de données dans Go
Comment créer un objet fonction à partir d'une chaîne
Diverses méthodes pour créer numériquement la fonction inverse d'une certaine fonction Introduction
[Circuit x Python] Comment trouver la fonction de transfert d'un circuit en utilisant Lcapy
Comment faire un Raspberry Pi qui parle les tweets d'un utilisateur spécifié
Créer une fonction pour visualiser / évaluer le résultat du clustering
Comment résoudre la fonction récursive qui a résolu abc115-D
#Une fonction qui renvoie le code de caractère d'une chaîne de caractères
Comment frapper le document de Magic Function (Line Magic)
Diverses méthodes pour créer numériquement la fonction inverse d'une certaine fonction Partie 1 Régression polynomiale
Comment créer une propriété de relations qui peuvent être prefetch_related par des conditions spécifiques
[Ubuntu] Comment supprimer tout le contenu du répertoire
J'ai fait une fonction pour vérifier le modèle de DCGAN
Comment exécuter automatiquement la fonction d'exportation de GCP Datastore
Comment trouver le coefficient de mise à l'échelle d'une ondelette bipolaire
Comment connecter le contenu de la liste dans une chaîne de caractères
[Linux] [C / C ++] Comment obtenir la valeur d'adresse de retour d'une fonction et le nom de fonction de l'appelant
Comment utiliser la fonction zip
Comment créer un package Conda
Comment créer une fonction récursive
Comment créer un pont virtuel
Comment créer un Dockerfile (basique)
Comment créer un fichier de configuration
Présentation de la création d'un socket serveur et de la création d'un socket client
Comment déterminer l'existence d'un élément sélénium en Python
[Introduction à Python] Comment fractionner une chaîne de caractères avec la fonction split
[Go] Créez une commande CLI pour changer l'extension de l'image
Comment vérifier la taille de la mémoire d'un dictionnaire en Python
Une fonction qui mesure le temps de traitement d'une méthode en python
Comment trouver l'adresse mémoire de la valeur de la trame de données Pandas
[Python3] Définition d'un décorateur qui mesure le temps d'exécution d'une fonction
Comment créer une grande quantité de données de test dans MySQL? ??
[python] Une note que j'ai commencé à comprendre le comportement de matplotlib.pyplot
[NNabla] Comment supprimer le niveau intermédiaire d'un réseau prédéfini
[Python] Une fonction simple pour trouver les coordonnées du centre d'un cercle
[Python] Un programme qui fait pivoter le contenu de la liste vers la gauche
Comment créer un clone depuis Github
Comment créer un dossier git clone
Comment vérifier la version de Django
Comment créer un référentiel à partir d'un média
Comment diviser et traiter une trame de données à l'aide de la fonction groupby
[Python] Explique comment utiliser la fonction range avec un exemple concret
[Python] Un programme qui calcule le nombre de chaussettes jumelées
[Introduction à Python] Comment trier efficacement le contenu d'une liste avec le tri par liste
Un mémorandum sur la façon d'écrire des pandas que j'ai tendance à oublier personnellement
[NNabla] Comment ajouter une couche de quantification à la couche intermédiaire d'un modèle entraîné
Comment mettre un numéro de ligne au début d'un fichier CSV
[Introduction à Python] Comment écrire une chaîne de caractères avec la fonction format
[Environnement de développement] Comment créer un ensemble de données proche de la base de données de production
Comment lire une vidéo tout en regardant le nombre d'images (Mac)
Python: je souhaite mesurer proprement le temps de traitement d'une fonction
[Python] Note: Fonction auto-conçue pour trouver la zone de distribution normale
J'ai créé une fonction pour voir le mouvement d'un tableau à deux dimensions (Python)
Créez un bot qui publie sur Slack le nombre de personnes positives pour le nouveau virus corona à Tokyo
Comment passer le résultat de l'exécution d'une commande shell dans une liste en Python
Comment trouver la zone du diagramme de Boronoi
Comment mentionner un groupe d'utilisateurs avec une notification de mou, comment vérifier l'ID d'un groupe d'utilisateurs
L'histoire de l'adresse IPv6 que je souhaite conserver au minimum