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 :

Appliquer un décorateur automatiquement à toutes fonctions et méthodes déclarées [Python 3.X]


Sujet :

Python

  1. #1
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut Appliquer un décorateur automatiquement à toutes fonctions et méthodes déclarées
    Salut à tous,

    Je me suis intéressé aux types des paramètres des fonctions en python, cette discussion m'a été utile, surtout dans l'idée d'utiliser un décorateur pour vérifier les types passés automatiquement.

    Que j'ai donc créé à ma sauce :

    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
    20
    21
    22
    23
    24
    # Décorateur vérifiant les types des paramètres reçus d'une fonction
    # En fonction des types déclarés dans sa définition
    def cfa(fn) :
        def icfa(*args, **dargs) :
            an = fn.__code__.co_varnames
            if args :
                dargs = {}
                for k, v in enumerate(args) :
                    dargs[an[k]] = v
            # Vérif des types
            for k, v in dargs.items() :
                if type(v) != fn.__annotations__[k] :
                    raise TypeError('Le type du paramètre "' + str(k) + '" doit être de type ' + fn.__annotations__[k].__name__ + ', fourni : ' + str(type(v).__name__))
            return(fn(**dargs))
        return icfa
     
    @cfa
    def tfd(nom:str, age:int, ville:str) -> None :
        print('coucou {0} tu as {1} ans et tu habites dans la ville de {2}.'.format(nom, age, ville))
     
     
    tfd('toto', 12, 'Dijon')
    tfd(**{'nom':'belle', 'age':15, 'ville':'Perpignan'})
    tfd(12, 19, True)
    Le truc, c'est qu'il faut chaque fois faire précéder chaque fonction créée de @cfa, ma question, est donc :
    Y'a t-il moyen d'appliquer ce décorateur à toutes les fonctions non built-in ou d'un autre module quelconque, donc seulement celles créées par l'utilisateur automatiquement ?
    Le temps ronge l'amour comme l'acide.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par bistouille Voir le message
    Y'a t-il moyen d'appliquer ce décorateur à toutes les fonctions non built-in ou d'un autre module quelconque, donc seulement celles créées par l'utilisateur automatiquement ?
    Pas facile de comprendre les décorateurs si vous n'avez pas compris "closures" et fonctions de fonctions:
    Soient "f" et "g" définies comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> def g(f):
    ...     def _inner_():
    ...         print('g: calling', f.__name__)
    ...     return _inner_
    ...
    >>> def f(): print('f')
    ...
    Décorer "f" c'est remplacer "f" par "g(f)":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> f = g(f)
    >>> f()
    g: calling f
    >>>
    Le '@' n'est que sucre syntaxique pour écrire la même chose sous la forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> @g
    ... def f(): print('f')
    ...
    >>> f()
    g: calling f
    >>>
    Vous pouvez donc récupérer toutes les fonctions d'un module ou toutes les méthodes d'une classe en utilisant les fonctionnalités d'inspect et les remplacer par leur équivalent décoré (ou pas n'importe quelle autre fonction).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,



    Pas facile de comprendre les décorateurs si vous n'avez pas compris "closures" et fonctions de fonctions:
    Soient "f" et "g" définies comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> def g(f):
    ...     def _inner_():
    ...         print('g: calling', f.__name__)
    ...     return _inner_
    ...
    >>> def f(): print('f')
    ...
    Décorer "f" c'est remplacer "f" par "g(f)":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> f = g(f)
    >>> f()
    g: calling f
    >>>
    Le '@' n'est que sucre syntaxique pour écrire la même chose sous la forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> @g
    ... def f(): print('f')
    ...
    >>> f()
    g: calling f
    >>>
    Merci pour cette explication, mais j'avais bine compris le fonctionnement

    Citation Envoyé par wiztricks Voir le message
    Vous pouvez donc récupérer toutes les fonctions d'un module ou toutes les méthodes d'une classe en utilisant les fonctionnalités d'inspect et les remplacer par leur équivalent décoré (ou pas n'importe quelle autre fonction).

    - W
    C'est justement là que je butais, en fait je le faisais de l'extérieur du module, ce qui ne fonctionne pas (j'ai pas tout saisi le fonctionnement interne avec les modules users, mais pas grave).
    D'autant qu'un help(monModule) contient bien la description du module alors qu'un dir(monModule) ne contient pas les composants du module.

    Donc faut le faire dans un fichier à l'intérieur du module, et ensuite appeler ce fichier depuis le script incluant le module, donc j'en conclus que ça ne peut-être automatiquement fait à l'import de façon transparente, sans appel d'un quelconque script.

    Hum, je suis pas sûr d'être clair dans mon explication
    Le temps ronge l'amour comme l'acide.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par bistouille Voir le message
    Merci pour cette explication, mais j'avais bine compris le fonctionnement
    Ben si vous avez compris le fonctionnement, pour remplacer une fonction dans un module:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> import os
    >>> os.getcwd()
    'F:\\py_samples'
    >>> os.getcwd = g(os.getcwd)
    >>> os.getcwd()
    g: calling getcwd
    note: c'est sur qu'on ne peut pas utiliser dans ce cas la syntaxe ''@' puisqu'on n'édite pas le module: on le modifie à la volée

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre éclairé
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Points : 751
    Points
    751
    Par défaut
    Citation Envoyé par bistouille Voir le message
    Hum, je suis pas sûr d'être clair dans mon explication
    Moyennement

    Citation Envoyé par bistouille Voir le message
    Donc faut le faire dans un fichier à l'intérieur du module, et ensuite appeler ce fichier depuis le script incluant le module, donc j'en conclus que ça ne peut-être automatiquement fait à l'import de façon transparente, sans appel d'un quelconque script.
    Tu peux mettre une variante de ce qu'a propose wiztricks dans le __init__.py de ton module:

    The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later (deeper) on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.

  6. #6
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Merci.

    Mais mon problème n'est pas là, évidemment que si je fais le tout statiquement, ça ne me pose aucun problème.

    C'est dans la façon de le faire dynamiquement qui l'est.
    Et manifestement c'est assez bancal de procéder ainsi, car il faut parcourir tout le bouzin, et faire des eval en pagaille.

    Oui, je m'étais d'abord orienté pour le mettre dans l'__init__ du module, mais non, dynamiquement c'est pas possible, puisque, après quelques tests, je me suis aperçu que ça me faisait une inclusion infinie (import), ce qui est somme toute assez logique.

    Tiens d'ailleurs à propos des __init__ des modules, j'ai une question sur une chose qui m'intrigue.
    Pourquoi certains developpeurs mettent tout leur code (enfin pas tout) dans l'__init__ de leur module ? Par exemple tkinter.
    Le temps ronge l'amour comme l'acide.

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par bistouille Voir le message
    C'est dans la façon de le faire dynamiquement qui l'est.
    Et manifestement c'est assez bancal de procéder ainsi, car il faut parcourir tout le bouzin, et faire des eval en pagaille.
    Pour remplacer un tas de fonctions par d'autres, difficile de se passer d'itérations & C°...

    Citation Envoyé par bistouille Voir le message
    Tiens d'ailleurs à propos des __init__ des modules, j'ai une question sur une chose qui m'intrigue.
    Pourquoi certains developpeurs mettent tout leur code (enfin pas tout) dans l'__init__ de leur module ? Par exemple tkinter.
    Le module Tkinter.py et d'autres Tk*.py existaient en Python2. Avec Python3, a été crée le module "tkinter" dans lequel tout a été poussé dedans avec un minimum de renommages. L'ancien Tkinter.py est devenu tkinter/__init__.py, car c'était le plus simple.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Merci des informations concernant tkinter.

    Citation Envoyé par wiztricks Voir le message
    Pour remplacer un tas de fonctions par d'autres, difficile de se passer d'itérations & C°...
    C° ?
    C ou C++ ?
    Le temps ronge l'amour comme l'acide.

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par bistouille Voir le message

    C° ?
    C ou C++ ?
    et compagnie...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    D'accord.

    Bon, ben on verra (beaucoup) plus tard pour le C, je ne m'y suis mit que très récemment

    Merci à vous deux d'avoir prit le temps de me répondre
    Le temps ronge l'amour comme l'acide.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. recalculer automatiquement toutes les fonctions d'une feuille
    Par lilly91 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 28/08/2010, 17h07
  2. envoyer un formulaire automatiquement toutes les 3 seconde
    Par rom62 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 15/05/2006, 15h08
  3. Réponses: 12
    Dernier message: 27/03/2006, 14h59
  4. Pointeur de fonctions sur méthode
    Par Glosialabolas dans le forum C++
    Réponses: 9
    Dernier message: 04/12/2005, 14h55
  5. [VB.NET] Appliquer plusieurs fois la même fonction...
    Par MiJack dans le forum Windows Forms
    Réponses: 9
    Dernier message: 22/09/2004, 10h52

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