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 :

getattr() ? Appel d'une fonction depuis une fonction


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Points : 36
    Points
    36
    Par défaut getattr() ? Appel d'une fonction depuis une fonction
    Bonjour,
    Voici un squelette de code (une fonction __init__ dans une classe. __init__ contient trois fonctions):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Foo()
    def __init__(...)
    def fonction()
    # ?? appel de la fonction autrefct ou autrefct1 avec leurs arguments ??
     
    def autrefct(a,b,c)
    self.fonction = sys._getframe().f_code.co_name # donne le string autrefct
     
    def autrefct1(d,e)
    self.fonction = sys._getframe().f_code.co_name # donne le string autrefct1
    Depuis la fonction fonction() je souhaite appeler une des fonctions autrefct avec leurs arguments propres. Comment fait-on celà? avec getattr()? J'ai cru comprendre que le deuxième argument de getattr est un string qui est le nom de la fonction à appeler (d'où les sys._getframe.....). Est-ce juste? Mais alors en l'occurrence quel est le premier argument de getattr? Comment fait-on passer passer les arguments des fonctions autrefct à fonction?
    Merci pour votre réponse!

  2. #2
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Salut,

    En fait c'est bien plus simple que ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class A(object):
      def __init__(self):
        def fonction():
          func2()
          func3()
        def func2(): print 'func2'
        def func3(): print 'func3'
        fonction()
     
    >>> a=A()
    func2
    func3

  3. #3
    Nouveau membre du Club
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Points : 36
    Points
    36
    Par défaut
    Oui merci ça je connaissais. Mais je souhaite faire cela avec une variable pour qu'une seul fonction soit appelée en fonction d'un critère particulier. Et je n'ai pas envie non plus d'utiliser une boucle if.

    En fait dans mon programme, la fonction fonction recharge la page courante définie par une des fonctions autrefct. Donc je veux que lorsqu'on demande de recharger la page (par Ctrl+N par exemple) la fonction déjà apparente soit rechargée (d'où la variable self.fonction).

    Maintenant que la finalité est je l'espère plus claire, la solution pourrait devenir plus évidente...

  4. #4
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Maintenant que la finalité est je l'espère plus claire, la solution pourrait devenir plus évidente...
    Pour ma part, ce serait en fait pas plus mal que tu réexpliques, ou au moins que tu réedites le code de la codebox dans ton premier post, cause je perçois le problème encore de la même façon...

  5. #5
    Nouveau membre du Club
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Points : 36
    Points
    36
    Par défaut
    Je vais essayer d'être plus précis.
    J'ai une application tkinter/python avec une barre de menus. L'utilisateur peut choisir entre plusieurs pages à afficher dans l'application principale, par exemple
    -page1 "contrôle journalier"
    -page2 "contrôle hebdomadaire"
    -page3 "contrôle mensuel"
    Chaque page contient un certains nombre de labels+entries et variables associées+callbacks pour faire des calculs avec les variables entrées. Ca donne un squelette comme ça:
    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
    class AppliPrincipale(Canvas)
       def __init__(...)
          def fonction(nouveau)
             effacetout()
             # ?? appel de la fonction contrJour ou contrHebdo ou contrMens avec leurs arguments ??
     
          def contrJour(a,b,c)
             self.fonction = sys._getframe().f_code.co_name
             Label(...).grid(...)
             Entry(...,textvariable=...).grid()
     
          def contrHebdo(d,e)
             self.fonction = sys._getframe().f_code.co_name
             Label(...).grid(...)
             Entry(...,textvariable=...).grid()
     
          def contrMens(f,g,h,i)
             self.fonction = sys._getframe().f_code.co_name
             Label(...).grid(...)
             Entry(...,textvariable=...).grid()
    Comme dans tout menu "fichier" qui se respecte, j'ai une option Nouveau qui appelle la fonction "nouveau". Cette fonction
    1-efface tous les widgets de la page (effacetout())
    2-relance la même fonction qui occupait la page (et donc aussi réexécute les callbacks).
    Voilà. Alors maintenant la question: comment faire le point 2 ci-dessus?
    J'ai pensé qu'avec getattr() je pouvais m'en sortir, d'où le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.fonction = sys._getframe().f_code.co_name
    qui apparaît dans chaque fonction pour en extraire le nom. Je sais que je peux utiliser la solution du message 2 avec une condition if:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if self.fonction == 'contrJour':
        contrJour()
    elif ...
    mais je souhaiterais une programmation en une ligne... Il doit bien exister une fonction qui permet de "coller" un string nom avec un string (*arguments) et ensuite d'exécuter le tout non?
    A noter que j'ai déjà essayé sans succès quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    f=locals()['nomdelafonction']
    f(*arguments)
    que j'ai lu qu'il fallait éviter d'utiliser eval() et que je pense que la solution est peut-être décrite dans http://keithdevens.com/weblog/archiv...unction.string
    mais que je n'ai pas réussi à l'appliquer dans mon cas.
    J'espère que l'intention est plus claire et je remercie par avance toute personne qui pourrait m'aider.

  6. #6
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Citation Envoyé par frites.saucisse Voir le message
    Je vais essayer d'être plus précis.
    J'ai une application tkinter/python avec une barre de menus. L'utilisateur peut choisir entre plusieurs pages à afficher dans l'application principale, par exemple
    -page1 "contrôle journalier"
    -page2 "contrôle hebdomadaire"
    -page3 "contrôle mensuel"
    Chaque page contient un certains nombre de labels+entries et variables associées+callbacks pour faire des calculs avec les variables entrées. Ca donne un squelette comme ça:

    ...code...

    Comme dans tout menu "fichier" qui se respecte, j'ai une option Nouveau qui appelle la fonction "nouveau". Cette fonction
    1-efface tous les widgets de la page (effacetout())
    2-relance la même fonction qui occupait la page (et donc aussi réexécute les callbacks).
    Voilà. Alors maintenant la question: comment faire le point 2 ci-dessus?
    Je vais essayer de te donner autre façon pour y arriver (au-delà de ce qui est cité, je suis perdu, je comprend pas...):

    _déja, je drirais d'éviter des fonctions definies à l'interieur de __init__ (ou autre méthode) si ton but est de les appeler ailleurs que depuis la méthode où elles ont étées définies. préférer des methodes directement

    _ il y aurait donc trois méthodes différentes (ou une méthode avec un paramètre servant à identifier la "page" à définir), chacunes pour définir les éléments de la fenêtre, ce qui veut dire que les éléments remplissant déjà la fenêtre (enfin, ceux définies par l'une des méthode précedentes) devront être effacés, donc...

    _chaques éléments définis par une des méthode de "définition de page", devrait être stockés dans un seul et même objet, une liste me paraît judicieux. Et dessinées, dans une Frame, ainsi pour effacer les éléments, y'a plus qu'a faire Frame.destroy()

    _toute les données (à l'état de stringVar ou de simple strings, c'est toi qui voit) des Entries d'une même "page", devront être gardée en mémoire (ou écrites sur DD, au choix) dans une liste, elle même stockée dans une autre liste ou un dico qui contiendrait également les autres listes de données

    Si chaques "page" suivent le même modèle, les même type de widgets, les même dispositions, alors c'est encore plus simple, il ne faut dans ce cas pas effacer les widgets, mais remplacer simplement leur donnée,

    Bon, comme j'ai la dalle, je ne vais pas écrire un code d'exemple. Normalement, si je me suis bien expliqué, cela devrait te suffire.

  7. #7
    Nouveau membre du Club
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Points : 36
    Points
    36
    Par défaut
    # 1: C'est vrai, je vais réécrire mon code dans ce sens.
    # 2: Je verrai ce point après, lorsque #1 sera fini.
    # 3 et #4: C'est comme cela que mon code marche déjà.

    Quand #1 sera fini, je verrai ce que je peux faire pour résoudre mon problème et si jamais, je reviendrai.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 119
    Points : 139
    Points
    139
    Par défaut
    je pense que ce que tu voulais initialement est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    getattr(o,functionname)(arguments)

  9. #9
    Nouveau membre du Club
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Points : 36
    Points
    36
    Par défaut
    Et ben voilà, maintenant que j'ai mis de l'ordre dans les fonctions, tout va mieux... Je reprends mon squelette avec la solution gettattr()

    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
    25
    26
    27
     
    class AppliPrincipale(Canvas)
     
      def nouveau(self)
             self.effacetout()
             getattr(self,self.fonction)(*self.arguments)
     
       def contrJour(self,a,b,c)
             self.arguments = (a,b,v)
             self.fonction = sys._getframe().f_code.co_name
             Label(...).grid(...)
             Entry(...,textvariable=...).grid()
     
       def contrHebdo(self,d,e)
             self.arguments = (d,e)
             self.fonction = sys._getframe().f_code.co_name
             Label(...).grid(...)
             Entry(...,textvariable=...).grid()
     
       def contrMens(self,f,g,h,i)
             self.arguments = (f,g,h,i)
             self.fonction = sys._getframe().f_code.co_name
             Label(...).grid(...)
             Entry(...,textvariable=...).grid()
     
       def __init__(...)
             Blablabla
    Encore merci pour cette suggestion, N.tox

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 25/05/2012, 20h55
  2. Réponses: 8
    Dernier message: 05/07/2011, 11h51
  3. Réponses: 17
    Dernier message: 15/04/2007, 12h28
  4. Réponses: 3
    Dernier message: 16/01/2006, 16h02

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