Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Appel d'une méthode d'un module depuis son nom

26 réponses
Avatar
Alain BARTHE
Bonjour,

J'ai créé un module contenant une grand nombre de fonctions, pour
traiter chacune un type de données.

Je lance ce module avec en argument un type de données (correspondant au
nom d'une des dites fonctions).

Pour appeler la fonction en question je procède comme suit :

def create_data (key):

"""fonction d'aiguillage vers les fonctions de traitement"""

fonction = globals () [key]

for x in .... :
fonction (x)

Je vais donc chercher la référence à ma fonction dans le dictionnaire
globals().

Par exemple :
create_data ("type_1")

doit appeler la fonction

def type_1 (argument):
...
Cela fonctionne parfaitement, mais j'aurais aimé savoir si c'était le
moyen de procéder le plus "propre" ?
N'y a t-il pas une autre façon sans le dictionnaire globals() ?

Merci d'avance.

10 réponses

1 2 3
Avatar
yves
Le Mon, 20 Jul 2009 20:08:50 +0200, Alain BARTHE a écrit:

Bonjour,

Cela fonctionne parfaitement, mais j'aurais aimé savoir si c'était le
moyen de procéder le plus "propre" ? N'y a t-il pas une autre façon sans
le dictionnaire globals() ?



Si tu n'es pas gêné par l'anglais, lit deux fois soigneusement:

http://www.freenetpages.co.uk/hp/alan.gauld/tutfunc.htm

Cordialement,
--
Yves
Avatar
Alain BARTHE
yves a écrit :
Le Mon, 20 Jul 2009 20:08:50 +0200, Alain BARTHE a écrit:

Bonjour,

Cela fonctionne parfaitement, mais j'aurais aimé savoir si c'était le
moyen de procéder le plus "propre" ? N'y a t-il pas une autre façon sans
le dictionnaire globals() ?



Si tu n'es pas gêné par l'anglais, lit deux fois soigneusement:

http://www.freenetpages.co.uk/hp/alan.gauld/tutfunc.htm

Cordialement,



Pas vu grand chose concernant mon problème là dedans.

J'ai pas du lire assez soigneusement.
Avatar
yves
Le Tue, 21 Jul 2009 09:51:57 +0200, Alain BARTHE a écrit:

Bonjour,

Pas vu grand chose concernant mon problème là dedans.



Tu as écrit:

Je lance ce module avec en argument un type de données



Pour moi, un module en python ne prend pas d'arguments (je peux me
tromper, je ne suis pas un cador).

Je t'ai donc renvoyé sur ce texte, qui explique assez bien (à mon avis)
ce que sont les modules en python.

Cordialement,
--
Yves
Avatar
yves
Le Tue, 21 Jul 2009 20:27:07 +0000, yves a écrit:

Je t'ai donc renvoyé sur ce texte, qui explique assez bien (à mon avis)
ce que sont les modules en python.



Par exemple, en condensé:

~/asup/essai $ ls
MonAutreProgramme.py MonModule.py MonProgramme.py
~/asup/essai $ cat MonModule.py
def type_1(argument):
return "je suis le type 1"
def type_2(argument):
return "je suis le type 2"
~/asup/essai $ cat MonProgramme.py
import MonModule
print MonModule.type_1("argument")
~/asup/essai $ python MonProgramme.py
je suis le type 1
~/asup/essai $ cat MonAutreProgramme.py
from MonModule import *
print type_2("argument")
~/asup/essai $ python MonAutreProgramme.py
je suis le type 2

Ceci clarifie-t'il les choses ?
--
Yves
Avatar
yves
Le Wed, 22 Jul 2009 09:35:09 +0200, Alain BARTHE a écrit:

Mon problème est de savoir si ma manière de procéder est la plus
correcte, notamment le passage par globals()



Oui, là le problème est clair.

Je n'ai pas d'opinion tranchée.
Voici un bout de code (d'Alan Gauld) qui peut donner des idées:

*********
def hello(): print 'hello'
def goodbye(): print 'goodbye'

menu = { '1' : ('hello', hello),
'Q' : ('goodbye', goodbye)}

print
for m in menu.keys():
print "%st%s" % (m,menu[m][0])

cmd = raw_input('pick one: ').upper()
menu[cmd][1]()
**********

Après adaptation au problème posé:
**********
import sys
def hello(): print 'hello'
def goodbye(): print 'goodbye'

menu = { 'hello' : hello,
'goodbye' : goodbye}
cmd = sys.argv[1]
menu[cmd]()
***********

La technique permet d'éviter le globals(), mais bon, fondamentalement
c'est la même chose.
Faudrait d'autres avis, mais tout le monde semble en vacances.

Cordialement,
--
Yves
Avatar
Pierre Quentel
On 23 juil, 02:23, yves wrote:
Le Wed, 22 Jul 2009 09:35:09 +0200, Alain BARTHE a écrit:

> Mon problème est de savoir si ma manière de procéder est la plus
> correcte, notamment le passage par globals()

Oui, là le problème est clair.

Je n'ai pas d'opinion tranchée.
Voici un bout de code (d'Alan Gauld) qui peut donner des idées:

*********
def hello(): print 'hello'
def goodbye(): print 'goodbye'

menu = { '1' : ('hello', hello),
         'Q' : ('goodbye', goodbye)}

print
for m in menu.keys():
   print "%st%s" % (m,menu[m][0])

cmd = raw_input('pick one: ').upper()
menu[cmd][1]()
**********

Après adaptation au problème posé:
**********
import sys
def hello(): print 'hello'
def goodbye(): print 'goodbye'

menu = { 'hello' : hello,
         'goodbye' : goodbye}
cmd = sys.argv[1]
menu[cmd]()
***********

La technique permet d'éviter le globals(), mais bon, fondamentalement
c'est la même chose.
Faudrait d'autres avis, mais tout le monde semble en vacances.

Cordialement,
--
Yves



Bonjour,

Je suis du même avis qu'Yves. En général l'utilisation de globals()
est considérée comme pas très élégante, mais dans ce cas de figur e je
ne vois pas de solution franchement meilleure. Le seul avantage de
gérer explicitement un dictionnaire des fonctions serait d'éviter un
possible conflit de noms avec globals(), mais c'est un peu tiré par
les cheveux comme argument

- Pierre
Avatar
Alain BARTHE
Pierre Quentel a écrit :
On 23 juil, 02:23, yves wrote:
Le Wed, 22 Jul 2009 09:35:09 +0200, Alain BARTHE a écrit:

Mon problème est de savoir si ma manière de procéder est la plus
correcte, notamment le passage par globals()


Oui, là le problème est clair.

Je n'ai pas d'opinion tranchée.
Voici un bout de code (d'Alan Gauld) qui peut donner des idées:

*********
def hello(): print 'hello'
def goodbye(): print 'goodbye'

menu = { '1' : ('hello', hello),
'Q' : ('goodbye', goodbye)}

print
for m in menu.keys():
print "%st%s" % (m,menu[m][0])

cmd = raw_input('pick one: ').upper()
menu[cmd][1]()
**********

Après adaptation au problème posé:
**********
import sys
def hello(): print 'hello'
def goodbye(): print 'goodbye'

menu = { 'hello' : hello,
'goodbye' : goodbye}
cmd = sys.argv[1]
menu[cmd]()
***********

La technique permet d'éviter le globals(), mais bon, fondamentalement
c'est la même chose.
Faudrait d'autres avis, mais tout le monde semble en vacances.

Cordialement,
--
Yves



Bonjour,

Je suis du même avis qu'Yves. En général l'utilisation de globals()
est considérée comme pas très élégante,



C'est bien pour cette raison que j'ai posé la question.

J'ai cherché rapidement dans la doc, mais je n'ai rien trouvé pour
l'instant.

mais dans ce cas de figure je
ne vois pas de solution franchement meilleure. Le seul avantage de
gérer explicitement un dictionnaire des fonctions serait d'éviter un
possible conflit de noms avec globals(), mais c'est un peu tiré par
les cheveux comme argument

- Pierre



Merci pour vos avis en tout cas.
Avatar
Alain Ketterlin
yves writes:

Mon problème est de savoir si ma manière de procéder est la plus
correcte, notamment le passage par globals()





[...]
def hello(): print 'hello'
def goodbye(): print 'goodbye'

menu = { 'hello' : hello,
'goodbye' : goodbye}
cmd = sys.argv[1]
menu[cmd]()
***********

La technique permet d'éviter le globals(), mais bon, fondamentalemen t
c'est la même chose.



J'ai tendance à préférer cette version à l'usage de glo bals(), mais je
n'ai pas vraiment d'argument décisif (surtout que globals() renvoie les
symboles du module, donc il y a peu de risque de conflit).

Cela dit, si tu veux épater ta belle-mère tu peux utiliser des
décorateurs :

reg = {}

def register(n):
def wrap(f):
reg[n] = f
return f
return wrap

@register("un")
def t_un():
return 1

@register("deux")
def t_deux():
return 2

reg[sys.argv[1]]()
# ...

Une raison de faire ça ? Euh... Ben ça fait une espèce de do cumentation.
Tu peux ajouter un test pour éviter de donner deux fois le même n om. Et
puis tu indiques exactement les fonctions qui vont servir de
gestionnaire. Et puis c'est plus moderne. Etc.

-- Alain.
Avatar
Francois
Alain BARTHE a écrit :

J'ai cherché rapidement dans la doc, mais je n'ai rien trouvé pour
l'instant.



Je suis loin d'être un spécialiste, mais je me lance quand même.

En fait, c'est au final la même idée qu'Yves (avec cette
astuce du "dictionnaire") mais avec des classes ici. On
pourrait remplacer le dictionnaire par un switch, mais il
paraît que c'est pas bien.

Mais je pense qu'il n'y a pas de miracle, à un moment donné,
il faut bien appeler la bonne fonction ou la bonne classe.


#-------------------------------------
import sys


class Type_general(object):
"""Une classe abstraite."""
def __init__(self):
pass

def traite(self): # methode pas implementee
raise NotImplementedError


class Type1(Type_general):
"""Une classe pas abstraite."""
def __init__(self):
Type_general.__init__(self)

def traite(self): # methode implementee
# Ici on me le code qui va bien
print "Traitement de Type1"


class Type2(Type_general):
"""Une classe pas abstraite."""

def __init__(self):
Type_general.__init__(self)

def traite(self): # methode implementee
# Ici on me le code qui va bien
print "Traitement de Type2"


class Constructeur_Type(object):
"""Classe qui va contruire les objets TypeX"""

def __init__(self):
pass

@staticmethod
def nouveau_type(un_type):
dico = {"Type1" : Type1,
"Type2" : Type2}
return dico[un_type]()


obj_type = Constructeur_Type.nouveau_type(sys.argv[1])
obj_type.traite()
#-------------------------------------


On appelle ce script par exemple avec :
$ python script.py "Type1"

Qu'en pensez vous ?



--
François Lafont
Avatar
moky
> Qu'en pensez vous ?



Je suis très très loin d'être expert en python (mais très près d'être un
NooB). Moi ce que j'en pense, c'est que je ne vois pas de cas où
j'aurais besoin d'appeler une méthode par son nom.

Si j'ai bien compris, le sport proposé dans ce fil est qu'on a un string
et qu'on veut lancer la fonction qui a pour nom ce string.

Donc, juste par curiosité : dans quel cas pratiques est-ce que le
problème se pose ?


Bonne aprème
Laurent
1 2 3