+ Répondre à la discussion Actualité déjà publiée
  1. #1
    Rédacteur/Modérateur

    Avatar de deusyss
    Homme Profil pro
    Ingénieur informatique/domotique/electronique/mecatronique
    Inscrit en
    mars 2010
    Messages
    1 608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur informatique/domotique/electronique/mecatronique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mars 2010
    Messages : 1 608
    Points : 7 779
    Points
    7 779

    Par défaut Tutoriel Introduction aux décorateurs en Python

    Bonjour à tous,

    Je vous propose un tutoriel introduction aux décorateurs Python.

    Bonne lecture
    "La connaissance appartient à tout le monde" (Film Antitrust)

    Tout le nécessaire pour Python:
    *News/Accueil *Cours/tutoriels *FAQ
    *Forums *Outils dédiés *Mon espace personnel avec mes Articles, Cours et Tutoriels

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    octobre 2011
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2011
    Messages : 61
    Points : 32
    Points
    32

    Par défaut

    Merci

  3. #3
    Membre averti Avatar de cervo
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2012
    Messages
    208
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : décembre 2012
    Messages : 208
    Points : 372
    Points
    372

    Par défaut

    Sympa l'article, je dirais que c'est a travers cet genre d'article qu'on se perfctionne. On a souvent une vue differente de ce que l'on avait avant la lecture...
    Toute chose dépend de la valeur qu'on lui attribue !

  4. #4
    Rédacteur/Modérateur

    Avatar de deusyss
    Homme Profil pro
    Ingénieur informatique/domotique/electronique/mecatronique
    Inscrit en
    mars 2010
    Messages
    1 608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur informatique/domotique/electronique/mecatronique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mars 2010
    Messages : 1 608
    Points : 7 779
    Points
    7 779

    Par défaut

    Heureux que ça plaise
    "La connaissance appartient à tout le monde" (Film Antitrust)

    Tout le nécessaire pour Python:
    *News/Accueil *Cours/tutoriels *FAQ
    *Forums *Outils dédiés *Mon espace personnel avec mes Articles, Cours et Tutoriels

  5. #5
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mai 2011
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : mai 2011
    Messages : 180
    Points : 321
    Points
    321

    Par défaut

    Bon article clair et concis.

    Quand j'ai débuté en Python, j'ai dû rapidement programmer des décorateurs sur les seules bases de la doc officielle et un ou l'autre exemple.
    Après quelque séances d'arrachage de cheveux, je les ai maîtrisés (sales bêtes ! ).

    Ton article devrais préserver l'intégralité capillaire de nos successeurs.

    Merci

  6. #6
    Membre averti
    Homme Profil pro
    Développeur banc de test
    Inscrit en
    mai 2014
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur banc de test
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : mai 2014
    Messages : 127
    Points : 321
    Points
    321

    Par défaut

    Bonjour,

    article très intéressant.


    Pour avoir fait du C je trouve une similitude des décorateurs avec le code préprocesseur, dans la possibilité de modifier la définition d'une fonction juste en passant un "alias" à l'aide de #define qu'on peut mettre sous condition #if #else etc... on gagne énormément en écriture et flexibilité du code.

    Pour aller un peu plus loin et essayer de rendre le décorateur le plus discret possible, qu'il ne modifie pas les héritages de la déclaration d'origine :

    En reprenant l'exemple du chapitre III.

    J'ai rajouté quelques docstring pour l'explication

    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
    16
    def mon_decorateur(fonction):
        def ma_fonction_decoree():
            """ma fonction décorée
            """
            print(fonction.__name__ + ' appelée')
            fonction()
        return ma_fonction_decoree
     
    @mon_decorateur
    def ma_fonction():
        """ma fonction affiche hello world
        """
        print("hello_world")
     
    if __name__ == "__main__":
        ma_fonction()
    Si on interroge la fonction ma_fonction sur son propre nom et son docstring :

    ma_fonction.__name__ va retourner 'ma_fonction_decoree'

    De même avec help(ma_fonction)

    Help on function ma_fonction_decoree in module __main__:

    ma_fonction_decoree()
    ma fonction décorée
    Chose embêtante si on utilise le même décorateur sur plusieurs fonctions, ça ne facilite pas l'introspection des fonctions.

    Voici donc comment améliorer ça et rendre le décorateur quasiment transparent pour la fonction décorée :


    Méthode 1: Remplacement des attributs manuellement

    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
    16
    17
    18
    def mon_decorateur(fonction):
        def ma_fonction_decoree():
            """ma fonction décorée
            """
            print(fonction.__name__ + ' appelée')
            fonction()
        ma_fonction_decoree.__name__ = fonction.__name__
        ma_fonction_decoree.__doc__ = fonction.__doc__
        return ma_fonction_decoree
     
    @mon_decorateur
    def ma_fonction():
        """ma fonction affiche hello world
        """
        print("hello_world")
     
    if __name__ == "__main__":
        ma_fonction()
    ma_fonction.__name__ va retourner 'ma_fonction'

    Avec help(ma_fonction)

    Help on function ma_fonction in module __main__:

    ma_fonction()
    ma fonction affiche hello world
    On peut connaître la liste des attributs à l'aide de la commande : dir(ma_fonction)


    Méthode 2: Remplacement des attributs automatiquement

    La librairie native functools dispose d'un décorateur (un de plus) wraps qui permet de faire hériter le décorateur des attributs de la fonction d'origine.

    L'utilisation est très simple :

    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
    16
    17
    18
    19
    import functools # Higher-order functions and operations on callable objects
     
    def mon_decorateur(fonction):
        @functools.wraps(fonction)
        def ma_fonction_decoree():
            """ma fonction décorée
            """
            print(fonction.__name__ + ' appelée')
            fonction()
        return ma_fonction_decoree
     
    @mon_decorateur
    def ma_fonction():
        """ma fonction affiche hello world
        """
        print("hello_world")
     
    if __name__ == "__main__":
        ma_fonction()
    __name__ et help fonctionne comme dans la première méthode

    En regardant dans la librairie \Lib\functools.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    # update_wrapper() and wraps() are tools to help write
    # wrapper functions that can handle naive introspection
     
    WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
                           '__annotations__')
    On réduit donc l'assignement de 5 attributs en une seule ligne. Vive les décorateurs de décorateurs !




    Pour aller plus loint :

    Voici juste un exemple de décorateur qui modifie les arguments passés par la fonction d'origine :

    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
    16
    17
    18
    import functools # Higher-order functions and operations on callable objects
     
    def convert_args(*types_args, **kw):
        def decorator(func):
            @functools.wraps(func)
            def newf(*args):
                """newf"""
                return func(*(type_arg(arg) for arg, type_arg in zip(args, types_args)))
            return newf
        return decorator
     
    @convert_args(float, int, str, lambda x:x+1)
    def function(*args):
        """Hello
        """
        return [0, ] + list(args)
     
    print(function(1, 2, 3, 4)) # [0, 1.0, 2, '3', 5]
    Les arguments 1, 2, 3, 4:
    1 est converti en float
    2 est converti en int, si ce n'était pas le cas
    3 est converti en string
    4 est incrémenté par la fonction lambda

    function retourne une liste avec 0 + les arguments convertis par le décorateur.

    C'est vraiment puissant comme concept !

  7. #7
    Rédacteur/Modérateur

    Avatar de deusyss
    Homme Profil pro
    Ingénieur informatique/domotique/electronique/mecatronique
    Inscrit en
    mars 2010
    Messages
    1 608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur informatique/domotique/electronique/mecatronique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mars 2010
    Messages : 1 608
    Points : 7 779
    Points
    7 779

    Par défaut

    Je vois que l'article plaît, cela fait plaisir.

    Merci pour les exemple complémentaire. J'ai appris l'existence de la lib functools. Je tâcherais d'inclure tout cela dans une future mise à jour
    "La connaissance appartient à tout le monde" (Film Antitrust)

    Tout le nécessaire pour Python:
    *News/Accueil *Cours/tutoriels *FAQ
    *Forums *Outils dédiés *Mon espace personnel avec mes Articles, Cours et Tutoriels

Discussions similaires

  1. Réponses: 0
    Dernier message: 02/02/2010, 21h51

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