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
Alain Ketterlin
moky writes:

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.



C'est exactement cela.

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



Par définition, lorqu'on a du texte au départ. Un cas simple sera it
celui d'un programme qui lit un fichier de données (disons ligne par
ligne), et que les données peuvent être de différents types. par exemple
le fichier suivant :

LIGNE 0 0 2 3
DISQUE 3 5 2
CARRE 8 4 6
TRIANGLE 0 1 5 4 2 8

etc. Tu pourrais imaginer que le programme lise chaque ligne, examine le
premier champ pour savoir de quel type il va avoir besoin, puis appelle
une fonction qui se charge des autres champs. Quelque chose du style :

traitement[ligne[0]](ligne[1:])

C'est un peu plus simple que de faire une énorme cascade de if, et
éventuellement c'est plus facile à maintenir : ajouter un type re vient à
écrire la fonction et la placer dans le dictionaire.

Dans la pratique, ça arrive assez souvent dès qu'on échange des données
sous forme de texte. Si tu veux par exemple charger en mémoire le
contenu d'un fichier XML, tu vas te retrouver face au même problè me. Et
il y a sûrement des tas d'autres cas.

Note aussi que ça peut être utile même quand l'index n'est p as une
chaîne de caractères, mais, par exemple, une constante dans une
énumération.

-- Alain.
Avatar
Alain BARTHE
moky a écrit :
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 ?



En fait je dois générer des fichiers d'entêtes contenant les
méta-données descriptives de fichiers de données scientifiques.

J'ai un assez grand nombre de type de données (une dizaine) qui peuvent
être générés pour plusieurs unités physiques, pour plusieurs satellites,
etc...

J'utilise pour créer ces fichiers un système de template (avec
string.Template) par type de fichier, et il faut créer un dictionnaire
pour remplir les variables du template.

Bref un grand nombre de fichiers différents, avec des cas particuliers
dans tous les sens, etc...

Pour cela j'ai créé une fonction par type de fichier, qui embarque
toutes les spécificités du type de fichier à générer (pour quel
satellite, quelles unités physiques, quels cas particuliers, etc...)

Je veux donc appeler à la demande une de ces fonctions, en passant son
nom en paramètre, qui est suffisamment parlant pour nous.

C'est vrai que je peux passer par un menu, mais ça m'oblige juste à
rajouter du code pour le gérer, sans apporter grand chose de plus.

Une des richesses de Python est justement de pouvoir faire de
l'introspection, d'interroger un module pour connaître les attributs,
les fonctions qu'il propose.

Pourquoi donc ne pas utiliser cette possibilité ?

La solution que j'ai utilisée fonctionne parfaitement, je voulais juste
savoir s'il n'y avait une méthode plus propre.

Merci quand même pour vos conseils.



Bonne aprème
Laurent


Avatar
Gael Lickindorf
pour appeler simplement une fonction à partir de son nom, utilisez
eval:

def DISQUE():
print 'fonction disque'

if __name__ == '__main__':
ligne = "DISQUE 3 5 2"
function_name = ligne.split()[0]
print function_name
eval(function_name)()

on obtient:
DISQUE
fonction disque
Avatar
Gael Lickindorf
On 27 juil, 16:10, Gael Lickindorf
wrote:
pour appeler simplement une fonction à partir de son nom, utilisez
eval:

def DISQUE():
    print 'fonction disque'

if __name__ == '__main__':
    ligne = "DISQUE 3 5 2"
    function_name = ligne.split()[0]
    print function_name
    eval(function_name)()

on obtient:
DISQUE
fonction disque



si la fonction est dans mon_module.py

import mon_module
module_name = 'mon_module'
function_name = 'DISQUE'
eval(module_name + '.' + function_name)()
Avatar
Alain BARTHE
Gael Lickindorf a écrit :
On 27 juil, 16:10, Gael Lickindorf
wrote:
pour appeler simplement une fonction à partir de son nom, utilisez
eval:

def DISQUE():
print 'fonction disque'

if __name__ == '__main__':
ligne = "DISQUE 3 5 2"
function_name = ligne.split()[0]
print function_name
eval(function_name)()

on obtient:
DISQUE
fonction disque



si la fonction est dans mon_module.py

import mon_module
module_name = 'mon_module'
function_name = 'DISQUE'
eval(module_name + '.' + function_name)()



Le eval() on me l'a déjà fortement déconseillé...
sur ce forum et ailleurs.

Merci quand même
Avatar
Bruno Desthuilliers
Francois a écrit :
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.



C'est surtout que c'est impossible - il n'y a pas de 'switch' en Python.
Avatar
Bruno Desthuilliers
moky a écrit :
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.



C'est pourtant un pattern très courant. Mais bon, comme beaucoup de
fonctionalités des langages un peu évolués, on n'en voit pas l'intérêt
tant qu'on a pas intégré l'idiome - après, on se demande comment on a pu
vivre sans.

Dans la pratique, c'est très utile pour gérer les interactions
utilisateurs, entre autres (mais pas uniquement) dans le cadre de
programmes en ligne de commande ou d'applications web.
Avatar
Michel Claveau - NoSpam SVP ; merci
Bonsoir !

Certes, SWITCH n'existe pas.
Mais, on peut essayer de le simuler (voir ci-dessous)

@+
--
Michel Claveau



def exe(st):
fcod=compile(st,'switch '+str(st),'exec')
exec(fcod,globals(),globals())

def switch(valeur):
def cas(compar,ordre,buffer=valeur):
if compar==buffer:
exe(ordre)
return cas


a1
b"2
c33
dD4

zz=b
case=switch(zz)
case(111,"print zz")
case(222,"""print 222
print '''Test multi-ligne
pour voir'''
print 'd =',d
zz=d
print zz""")
case(333,"print 333")
case(444,"print 444")


case=switch(zz)
case(111,"print zz")
case(222,"print 222")
case(333,"print 333")
case(444,"print 444")
Avatar
handraiser
On 20 juil, 20:08, Alain BARTHE wrote:
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 a u
  nom d'une des dites fonctions).



Lisez le fichier args.py (et commands.py, que vous devrez réécrire
pour y mettre vos fonctions) du code source de lamson (http://
lamsonproject.org/). Zed Shaw a déjà écrit le code qui fait ce que
vous voulez. Adaptez juste les fichiers à votre cas (à noter que
Z.Shaw utilise l'attribut __dict__ du module contenant les fonctions :
m.__dict__(func_name)).
Avatar
handraiser
On 23 juil, 10:01, Pierre Quentel wrote:
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



On n'a pas besoin de gérer explicitement un dictionnaire. À
l'importation d'un module, Python crée lui-même dynamiquement un
dictionnaire comprenant les noms définis dans le module.

import blah
blah.__dict__

Une solution simple et 'clean' est donc de mettre toutes les fonctions
dans un module et de l'importer dans le programme qui les utilise.
1 2 3