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 :

Appeller une fonction avec un string


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Septembre 2011
    Messages : 17
    Points : 36
    Points
    36
    Par défaut Appeller une fonction avec un string
    Bonjour à tous !

    J'essaye de comprendre comment appeller une fonction seulement à partir de son nom (stocké dans un string), et mes recherhes mènent toutes au même genre de réponse, à savoir utiliser getaddr. Cela donne généralement :

    result = getattr(foo, 'bar')()

    Avc bar = nom de la fonction. Le problème, c'est que je ne vois pas du tout ce qu'est censé être foo ! Les définitions de getattr me parlent d'un "objet" ou d'un "module" mais cela ne correspond à rien dans mon programme... Est-ce une erreur de conception de ma part ou de compréhension de ce getattr ? Merci d'avance de m'éclairer un peu...

  2. #2
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    J'essaye de comprendre comment appeller une fonction seulement à partir de son nom (stocké dans un string)
    Edit : Pourquoi dans un string?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> def add(a, b):
    	return a+b
     
    >>> def sub(a, b):
    	return a-b
     
    >>> my_func = [add, sub]
    >>> for func in my_func:
    	print(func(3, 5))
     
     
    8
    -2
    getattr(objet, 'data') il permet de donner l'attribut data de l'objet.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> class A:
    	pass
     
    >>> a = A()
    >>> a.data = 6
    >>> getattr(a, 'data')
    6
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  3. #3
    Membre averti Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Points : 329
    Points
    329
    Par défaut
    si mes souvenirs sont bon, la fonction devrait pouvoir faire l'affaire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    def f1():
    	print 'ok'
     
    s1 = "f"
    s2 = "1"
     
    s3 = s1 + s2 + "()"
     
    exec(s3)
    Voilou
    Memento Quia Pulvis Es, Et In Pulverem ReverteriS

  4. #4
    Membre éclairé
    Avatar de panda31
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Juin 2003
    Messages
    670
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Juin 2003
    Messages : 670
    Points : 848
    Points
    848
    Par défaut
    Getattr est bon si on connait l'objet dans lequel chercher la méthode ou l'attribut de cet objet.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class A:
    	def myMethod(self, a, b):
    		print "argument 1 : "+a+", argument 2 : "+b
     
    if __name__ == "__main__":
    	obA = A()
    	func = getattr(obA, "myMethod")
    	func("chose", "truc")
    L'exécution donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    argument 1 : chose, argument 2 : truc
    Si tu veux plus d'aide, détaille un peu plus ta demande.
    Bon code!
    Michaël Mary
    Consultant PLM dans une société de conseil toulousaine
    Auditeur CNAM-IPST depuis septembre 2008
    "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."
    John F. Woods
    mon cv et mon domaine et mon blog
    Aucune question technique par MP, svp

  5. #5
    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 Thibqult Voir le message
    Avec bar = nom de la fonction. Le problème, c'est que je ne vois pas du tout ce qu'est censé être foo ! Les définitions de getattr me parlent d'un "objet" ou d'un "module" mais cela ne correspond à rien dans mon programme...
    Python crée cela pour vous...

    Pensez getattr comme une fonction recherchant la définition d'un nom dans un espace (de noms "plat"). Avec Python tout est "objet" et tous les objets appartiennent à un "module". Un module pourrait être considéré comme un objet particulier mais...

    Exemple:
    >>> int.__module__
    '__builtin__'

    ** but ** le string '__builtin__' n'est pas le module qui se récupère via:
    >>> module = sys.modules['__builtin__']
    >>> x = getattr(module, 'int')
    >>> x
    <type 'int'>

    Est-ce une erreur de conception de ma part ou de compréhension de ce getattr ? Merci d'avance de m'éclairer un peu...
    Pas facile de concevoir proprement lorsqu'on ne comprend pas... Donc je dirais les deux mon capitaine, mais prenez le temps d'apprendre et çà ira bien.

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

  6. #6
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Et passer par globals(), à partir du moment où la fonction est dans le script lui-même ou a été importée nommément ?

    dans plus.py :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def plus(a,b):
        return a+b
    script.py :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import sys 
     
    from plus import plus
     
    def moins(a,b):
        return a-b 
     
    def calcule(operation,entier_1,entier_2):
        function = globals()[operation]
        return function(entier_1,entier_2)
     
    if __name__ == '__main__':
        print calcule(sys.argv[1],int(sys.argv[2]),int(sys.argv[3]))
    à l'usage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $> python script.py plus 4 5
    9
    $> python script.py moins 4 5
    -1
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  7. #7
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    @Pymento

    La fonction exec n'est surtout pas une bonne chose en python, on l'utilise vraiment que lorsqu'elle est indispensable car c'est une fonction source de bugs, de manque de contrôle de son programme, de destruction des performances, etc...

    Martelli lui même en parle de cette façon

    Use exec only when it's really indispensable
    Hors dans ce cas, ça ne l'est pas.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  8. #8
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2010
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2010
    Messages : 140
    Points : 182
    Points
    182
    Par défaut executer du string
    Bonjour, tu peux exécuter une chaîne de caractère avec la fonction eval comme il suit

    je ne sais pas exactement ce que tu peux faire de plus avec
    sinon, autre solution :
    tu ecris ton code dans un fichier et tu l'importes ensuite genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    c = open('toto.py')
    c.write(moncode)
    c.close()
    from toto import *

  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
    Je comprends qu'à la vue d'un string certains puissent perdre leur sang froid mais la question initiale portait sur getattr et non sur comment écrire un "interpréteur" de commandes ingérable.
    - W
    PS: Si tel était le cas, les modules cmd et shlex sont à regarder.
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Bonjour, tu peux exécuter une chaîne de caractère avec la fonction eval comme il suit
    Il y a le module ast, qui est plus safe que la fonction builtin eval().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> import ast
    >>> ast.literal_eval('2+1')
    3
    Je comprends qu'à la vue d'un string certains puissent perdre leur sang froid mais la question initiale portait sur getattr
    Dans ce cas je n'utiliserais pas getattr mais cette solution

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> def test(a):
    	return a
     
    >>> print(globals()['test'](5))
    5
    Edit : Je crois avoir été grilled par plxpy
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  11. #11
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    mais la question initiale portait sur getattr
    Non. Getattr est ce qu'avait trouvé Thibqult pour tenter de résoudre son problème qui était initialement de :

    comment appeller une fonction seulement à partir de son nom (stocké dans un string)
    comment écrire un "interpréteur" de commandes ingérable
    L'exemple choisi n'avait pour but que de montrer que ça fonctionnait, rien d'autre. Je ne sais pas ce que Thibqult souhaite faire.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  12. #12
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Petit complément: il est quelquefois intéressant de conserver la relation nomdefonction <=> fonction avec un dictionnaire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def plus(x, y):
        return x+y
     
    def moins(x, y):
        return x-y
     
    Op = {"plus": plus, "moins": moins}
     
    print Op["plus"](5,4)
    9
    print Op["moins"](5,4)
    1
    Ça permet de simuler un "case of" inexistant sous Python
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  13. #13
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    @wiztricks: Par contre, vraiment sans polémiquer et en dehors du côté "interpréteur de commandes ingérable", j'aimerais bien que tu me/nous donnes des conseils sur l'utilisation de globals() pour ce genre de problème. Est-ce propre ? A quels problèmes on s'expose en procédant de la sorte , etc ...
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  14. #14
    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 plxpy Voir le message
    Par contre, vraiment sans polémiquer et en dehors du côté "interpréteur de commandes ingérable", j'aimerais bien que tu me/nous donnes des conseils sur l'utilisation de globals() pour ce genre de problème. Est-ce propre ? A quels problèmes on s'expose en procédant de la sorte , etc ...
    globals() permettra de récupérer la définition de symboles dans le module courant. getattr sera plus générique. Le côté "fonctionnel" s'arrête là.

    Le fait est que si on se pose la question, c'est qu'on a récupéré des chaînes de caractère d'on ne sait où et qu'on a peut être envie de "contrôler" plus précisément la liste des symboles qu'on se proposera de...

    Ce qui n'a rien à voir avec le côté "fonctionnel" mais a plutôt trait à la sécurité ou à l'affichage de message d'erreurs circonstanciés.

    Une réponse est ce que propose Tyrtamos: les symboles à traduire sont stockés dans un dict.
    Ce pas là franchit, plus besoin de passer par "globals"!

    Mais on pourrait très bien emballer les fonctions dans une classe et se servir de la boîte "classe" ou "instance" (et getattr) plutôt que d'un dict simple.

    Cela pourrait donner une chose de la forme:

    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
    class A:
        @classmethod
        def _plus(cls, x, y):
            return x+y
     
        @classmethod
        def _moins(cls, x, y):
            return x-y
     
        @classmethod
        def call(cls, name, *args, **kwds):
            name = '_' + name
            if hasattr(cls, name):
                return getattr(cls, name)(*args, **kwds)
     
    print A.call('plus', 1, 2)
    print A.call('moins', 1, 2)
    Ce qui est un peu "over-engineered" pour ce cas particulier.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  15. #15
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    @wiztricks Merci pour ces précisions
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  16. #16
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Citation Envoyé par wiztricks Voir le message
    globals() permettra de récupérer la définition de symboles dans le module courant.
    En soit n'est il pas risqué de 'stocker' quelque chose dans une boite aussi 'volatile' (les dicos global) ?
    Cela n'a pas d'importance ici mais pour du code plus important n'est ce pas le meilleur moyen de 'perdre des petits en route' ?
    Outre l'aspect 'injection' le fait d'avoir une 'boite' (objet) bien définie me semble la meilleure façon de 'suivre' ses variables, non ?
    Quant a getattr il a au moins l'avantage de limiter les 'dégâts'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    >>> class A:
    ...     pass
    ... 
    >>> getattr(A, 'toto')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: type object 'A' has no attribute 'toto'
    >>> class A:
    ...      toto=1
    ... 
    >>> getattr(A, 'toto')
    1
    @+
    Merci d'utiliser le forum pour les questions techniques.

  17. #17
    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 PauseKawa Voir le message
    En soit n'est il pas risqué de 'stocker' quelque chose dans une boite aussi 'volatile' (les dicos global) ?

    Cela n'a pas d'importance ici mais pour du code plus important n'est ce pas le meilleur moyen de 'perdre des petits en route' ?
    En python, tout étant "dynamique".... je ne connais pas de boîtes qui soient des "coffres forts" inviolables.

    classe ou module, ce qui me semble "important", c'est la durée de vie de l'objet: tous deux sont, par défaut, crées et détruits au lancement et à la fin... mais le premier paramètre de getattr fonctionne avec les deux...

    note: en fait tout est dans des dict plus ou moins aménagés...

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

  18. #18
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    En python, tout étant "dynamique".... je ne connais pas de boîtes qui soient des "coffres forts" inviolables.

    classe ou module, ce qui me semble "important", c'est la durée de vie de l'objet: tous deux sont, par défaut, crées et détruits au lancement et à la fin... mais le premier paramètre de getattr fonctionne avec les deux...

    note: en fait tout est dans des dict plus ou moins aménagés...
    C'est bien le sens de mes 'questions': La visibilité et le type de la 'boite'.
    La 'boite' class boite(dict) me semble bien pour du code propre.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  19. #19
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Un truc continue à me turlupiner. Vous êtes plusieurs à éviter autant que possible d'utiliser globals() - le dictionnaire retourné - avec, comme clé, le nom de la fonction à appeler.

    J'ai le vague sentiment que, dans certains cas, l'utilisation directe du dictionnaire retourné par globals() est préférable* (moins d'intermédiaires, code plus "ramassé" et plus lisible) à l'utilisation d'un dictionnaire géré à la main, qui associerait mots-clés/noms de fonction avec les fonctions, résultat d'un "switch" (if ... elif) géant Non, vu que c'est un dictionnaire - c'est l'initialisation, clé/fonction, une à une qui peut être lourdingue.

    (*) du moins, il ne faut pas l'exclure d'emblée

    Aussi, y-a-t-il, fondamentalement, une différence entre :

    exécuter l'intruction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    globals()[nom_fonction](parametres)
    avec nom_fonction valant "fonction"

    et ecrire, dans le code lui-même,

    Sous la deuxième forme, à l'exécution, l'interpréteur va rechercher le symbole nom_fonction dans l'espace de nommage local, ne pas le trouver (sauf si on est, par exemple, dans le main où locals() et globals() retournent la même chose), dans l'espace de nommage global qui est censé être récupérable via, justement, globals() et, s'il le trouve, (tenter de) lancer/appeler la dite-fonction.

    Si la fonction n'existe pas, on n'aura seulement des exceptions différentes levées (NameError ou KeyError) selon l'approche.


    Est-ce que je loupe quelque chose en faisant ce raisonnement ?
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  20. #20
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour plxpy,

    Pour être franc (et je me trompe sans doute):
    Pour moi les namespaces font partis de la tuyauterie interne, que ce soit globals() ou locals() ce n'est qu'un accès (représentation sous forme de dico) aux espaces de nom 'global' et 'local' (block).
    Certes il est possible d'écrire directement dedans (non recommander pour le local bien sur) mais key = valeur en fait autant et c'est l'interpréteur qui le gère. Je préfère cela.
    Ensuite viens le namespace pollution. On y ajoute quelques from tutu import * et nous voila avec une belle pagaille.
    Pour finir le suivi des objets. Je trouve plus propre de faire mondico[key] que globals[key]. A moins je sais ce qu'est 'key' dans mon dico, dans le globals (qui est en r/w) je risque d'avoir des surprises. Cela fait un appel global de plus ? globals[key] aussi (et interdit de faire mumuse avec le local).
    C'est juste un avis personnel sur mon approche d’autodidacte de Python.

    @+
    Merci d'utiliser le forum pour les questions techniques.

Discussions similaires

  1. Appeler une fonction avec un string
    Par wazzzzza dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 01/02/2011, 12h56
  2. Appel de fonction avec un string
    Par james_kirk dans le forum Windows Forms
    Réponses: 4
    Dernier message: 26/04/2008, 04h39
  3. Appeler une fonction avec un tableau en parametre ?
    Par devoluti0n dans le forum C++
    Réponses: 9
    Dernier message: 11/04/2008, 16h21
  4. Appeler une fonction avec "action" ds un
    Par drinkmilk dans le forum ASP
    Réponses: 4
    Dernier message: 20/04/2004, 14h54
  5. Appeler une fonction avec/sans parenthèses
    Par haypo dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 29/12/2002, 18h48

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