2118 votes

Appeler une fonction d'un module en utilisant son nom (une chaîne de caractères)

Comment appeler une fonction en utilisant une chaîne avec le nom de la fonction? Par exemple:

import foo
nom_func = "bar"
appel(foo, nom_func)  # appelle foo.bar()

1 votes

En utilisant eval susciterait probablement certaines inquiétudes en matière de sécurité !

0 votes

Rappel : la fonctionnalité du langage d'accéder aux champs, aux classes et aux méthodes par des noms dynamiques est appelée réflexion. Cela pourrait rendre les futures recherches plus faciles.

2549voto

Patrick Johnmeyer Points 5947

Étant donné un module foo avec la méthode bar:

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

getattr peut également être utilisé sur des méthodes liées à des instances de classe, des méthodes au niveau du module, des méthodes de classe... la liste est longue.

16 votes

Hasattr ou getattr peut être utilisé pour déterminer si une fonction est définie. J'avais un mappage de base de données (type d'événement et fonction de traitement) et je voulais m'assurer de ne jamais "oublier" de définir un gestionnaire d'événements dans mon Python

12 votes

Cela fonctionne si vous connaissez déjà le nom du module. Cependant, si vous voulez que l'utilisateur fournisse le nom du module en tant que chaîne de caractères, cela ne fonctionnera pas.

9 votes

Si vous avez besoin d'éviter une exception NoneType is not callable, vous pourriez également utiliser la forme à trois arguments de getattr: getattr(foo, 'bar', lambda: None). Je m'excuse pour la mise en forme; l'application Android de stackexchange est apparemment terrible.

660voto

sastanin Points 16061
  • A l'aide de locals(), qui renvoie un dictionnaire avec la table de symboles locale actuelle :

    locals()["myfunction"]()
  • A l'aide de globals(), qui renvoie un dictionnaire avec la table de symboles globale :

    globals()["myfunction"]()

74 votes

Cette méthode avec globals/locals est bonne si la méthode que vous devez appeler est définie dans le même module à partir duquel vous appelez.

0 votes

@Joelmob y a-t-il un autre moyen d'obtenir un objet par chaîne hors de l'espace de noms racine?

0 votes

@NickT Je ne connais que ces méthodes, je ne pense pas qu'il y en ait d'autres qui remplissent la même fonction que celles-ci, du moins je ne vois pas pourquoi il devrait y en avoir plus.

405voto

HS. Points 5414

Basé sur la solution de Patrick, pour obtenir le module de manière dynamique également, importez-le en utilisant :

module = __import__('foo')
func = getattr(module, 'bar')
func()

100 votes

Je ne comprends pas ce dernier commentaire. __import__ a ses propres droits et la phrase suivante dans les documents mentionnés dit : "L'utilisation directe de __import__() est rare, sauf dans les cas où vous souhaitez importer un module dont le nom n'est connu qu'à l'exécution". Donc : +1 pour la réponse donnée.

58 votes

Utilisez importlib.import_module. Les documents officiels disent à propos de __import__: "Il s'agit d'une fonction avancée qui n'est pas nécessaire dans la programmation Python quotidienne, contrairement à importlib.import_module()." docs.python.org/2/library/functions.html#__import__

9 votes

@glarrain Tant que vous êtes d'accord avec le fait de ne prendre en charge que la version 2.7 et plus.

142voto

Sourcegeek Points 171

Juste une simple contribution. Si la classe que nous devons instancier se trouve dans le même fichier, nous pouvons utiliser quelque chose comme ceci :

# Obtenir la classe des globaux et créer une instance
m = globals()['our_class']()

# Obtenir la fonction (de l'instance) que nous devons appeler
func = getattr(m, 'function_name')

# Appeler la
func()

Par exemple :

class A:
    def __init__(self):
        pass

    def sampleFunc(self, arg):
        print('vous avez appelé sampleFunc({})'.format(arg))

m = globals()['A']()
func = getattr(m, 'sampleFunc')
func('argument d'échantillon')

# Exemple, tout sur une seule ligne
getattr(globals()['A'](), 'sampleFunc')('argument d'échantillon')

Et, si ce n'est pas une classe :

def sampleFunc(arg):
    print('vous avez appelé sampleFunc({})'.format(arg))

globals()['sampleFunc']('argument d'échantillon')

0 votes

Que se passe-t-il si vous appelez cette fonction à l'intérieur d'une fonction de classe?

135voto

ferrouswheel Points 526

Étant donné une chaîne de caractères, avec un chemin python complet vers une fonction, voici comment j'ai procédé pour obtenir le résultat de ladite fonction :

import importlib
function_string = 'mypackage.mymodule.myfunc'
mod_name, func_name = function_string.rsplit('.',1)
mod = importlib.import_module(mod_name)
func = getattr(mod, func_name)
result = func()

3 votes

Cela m'a aidé. C'est une version allégée de la fonction __import__.

3 votes

Je pense que c'était la meilleure réponse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X