IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

[Dde d'avis] Décorateur pour vérif. arguments des fonctions


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut [Dde d'avis] Décorateur pour vérif. arguments des fonctions
    Bonjour,

    Jusqu'à présent, j'ai toujours soigneusement évité de toucher aux décorateurs. Je me méfiais de ces choses étranges, et je m'en passais facilement. Jusqu'au jour ou j'ai commencé à entrevoir des applications intéressantes.

    Je vous propose ici un décorateur pour vérifier les arguments d'appel d'une fonction ou d'une méthode. Les vérifications peuvent porter sur des conditions (ex: n>0) et sur les types (ex: n=int). Le tuto est ici: http://python.jpvweb.com/mesrecettes...eurs_verifargs. Vous pouvez essayer le décorateur avec un simple copier-coller.

    J'ai pensé à ce décorateur pour une calculatrice: chacune des fonctions de calcul peut être appelée avec les arguments saisis par l'utilisateur. Il est donc important de tester ces arguments, non seulement pour empêcher le plantage de cette calculatrice, mais aussi pour renvoyer à l'utilisateur un message d'erreur explicite afin qu'il puisse corriger. Donc, actuellement, TOUTES ces fonctions de calcul commencent par un code de vérification qui prend souvent plus de place que le code de calcul lui-même. On voit tout de suite l'intérêt du décorateur: cette vérification ne prendra désormais qu'une seule ligne écrite avant chaque fonction!

    Exemple d'utilisation sur une fonction "fonctiontest":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    @verifargs("a>=b", "c>=0", b=int, c=(int,long,float), d=(NoneType,str,unicode))
    def fonctiontest(a, b, c, d="toto", e=123):
        return a*b*c*e, d
    On voit bien à quel point ça simplifie le code: une fois le décorateur écrit, toutes les fonctions et méthodes d'un programme peuvent l'utiliser. Ce sont les arguments passés au décorateur qui définissent les vérifications à faire pour chaque fonction ou méthode.

    Exemples d'appel de cette fonction:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    r = fonctiontest(6, 5, 3.123, d=None)
    # appel réussi: toutes les conditions et tous les types sont ok
    # à noter que le type de la valeur None est vérifié grâce à NoneType du module standard types 
     
    r = fonctiontest(2, "truc", 3, d="toto")
    # échec: mauvais type pour b
    # à noter que la vérification sur les types est faite avant l'évaluation des conditions  
     
    r = fonctiontest(2, 5, 3, d="machin")
    # échec: condition a>=b non remplie
    # à noter que les types des arguments par défaut non passés (ici e=123) ne sont pas testés
     
    r = fonctiontest(6, 5, -3.123, d=None)
    # échec: condition c>=0 non remplie
    On peut, bien entendu, récupérer proprement les exceptions générées:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    try:
        r = fonctiontest(5, 5, -3.123, d=None)
    except (ValueError, TypeError) as e:
        print e
    J'ai essayé de penser à tout, mais je ne suis pas sûr d'avoir réussi: les personnes intéressées peuvent-elles me donner leur avis?

    Merci d'avance!

    Tyrtamos

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 762
    Par défaut
    Salut,

    Python3 introduit l'annotation des fonctions décrite dans le PEP 3107.
    Cela ne teste rien mais définit le standard côté déclaration et les API d'accès qu'il serait peut être intéressant d'utiliser.
    Le PEP mentionne aussi des bibliothèques qui font déjà cela sous Python2.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Salut,
    il y a des choses intéressantes dans le chapitre 8 de "Programming In Python 3" de Summerfield.

    Il y a l'exemple suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def positive_result(function):
        @functools.wraps(function)
        def wrapper(*args, **kwargs):
            result = function(*args, **kwargs)
            assert result >= 0, function.__name__ + "() result isn't >= 0"
            return result
        return wrapper
     
    @positive_result
    def discriminant(a, b, c):
        return (b ** 2) - (4 * a * c)
    L'usage de @functools.wraps(function) permet de garder le nom et la docstring de la fonction décorée.

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Merci, rambc, d'avoir attiré mon attention sur functools.wraps. Je l'avais vu dans des exemples sur le web, mais je n'avais pas compris ce qu'il faisait.

    Effectivement, sans l'utiliser, les nom et docstring de la fonction décorée sont remplacés. Voilà un exemple simplifié (Python 2.7):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    import functools
     
    def mondecorateur(fonc):
        #@functools.wraps(fonc)
        def appelfonc(*args, **kwargs):
            """Docstring de appelfonc"""
            return fonc(*args, **kwargs)
        return appelfonc
     
    @mondecorateur
    def exemple():
        """Docstring de exemple"""
        pass
    Tel quel, l'affichage des nom et docstring de exemple donne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    print exemple.__name__
    appelfonc
    print exemple.__doc__
    Docstring de appelfonc
    Et en décommentant la ligne @functools.wraps(fonc):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    print exemple.__name__
    exemple
    print exemple.__doc__
    Docstring de exemple
    A appliquer systématiquement!

    Merci!

    Tyrtamos

Discussions similaires

  1. [XL-2003] Conserver le nom de l'appli courante pour l'appel des fonctions
    Par comme de bien entendu dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 26/06/2011, 17h31
  2. Argument des fonctions
    Par snurok dans le forum MATLAB
    Réponses: 2
    Dernier message: 28/08/2010, 09h52
  3. Arguments des fonctions de callback avec GTKUIManager
    Par mathedit dans le forum GTK+ avec C & C++
    Réponses: 2
    Dernier message: 10/05/2009, 23h26
  4. [VBA-Excel]Avoir une boite de dialogue avec les arguments des fonctions ?
    Par EvaristeGaloisBis dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 29/05/2007, 09h37
  5. pointeurs sur les arguments des fonctions?
    Par brunoP dans le forum C
    Réponses: 3
    Dernier message: 14/05/2006, 18h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo