Question Appeler une fonction d'un module en utilisant son nom (une chaîne)


Quel est le meilleur moyen d'appeler une fonction donnée avec une chaîne avec le nom de la fonction dans un programme Python. Par exemple, disons que j'ai un module foo, et j'ai une chaîne dont le contenu est "bar". Quelle est la meilleure façon d'appeler? foo.bar()?

Je dois obtenir la valeur de retour de la fonction, c'est pourquoi je n'utilise pas seulement eval. J'ai compris comment le faire en utilisant eval pour définir une fonction temp qui retourne le résultat de cet appel de fonction, mais j'espère qu'il y a une façon plus élégante de le faire.


1185
2017-08-06 03:36


origine


Réponses:


En supposant le module foo avec méthode bar:

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

Dans la mesure où cela se passe, les lignes 2 et 3 peuvent être compressées pour:

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

si cela a plus de sens pour votre cas d'utilisation. Vous pouvez utiliser getattr de cette manière sur les méthodes liées aux instances de classe, les méthodes au niveau des modules, les méthodes de classe ... la liste continue.


1439
2017-08-06 03:57



locals()["myfunction"]()

ou

globals()["myfunction"]()

des locaux retourne un dictionnaire avec une table de symboles locale actuelle. globals retourne un dictionnaire avec une table de symboles globale.


401
2018-05-07 12:45



La solution de Patrick est probablement la plus propre. Si vous devez également prendre le module de manière dynamique, vous pouvez l'importer comme:

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

240
2017-08-07 11:35



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

# Get class from globals and create an instance
m = globals()['our_class']()

# Get the function (from the instance) that we need to call
func = getattr(m, 'function_name')

# Call it
func()

Par exemple:

class A:
    def __init__(self):
        pass

    def sampleFunc(self, arg):
        print('you called sampleFunc({})'.format(arg))

m = globals()['A']()
func = getattr(m, 'sampleFunc')
func('sample arg')

# Sample, all on one line
getattr(globals()['A'](), 'sampleFunc')('sample arg')

Et, si ce n'est pas une classe:

def sampleFunc(arg):
    print('you called sampleFunc({})'.format(arg))

globals()['sampleFunc']('sample arg')

81
2017-08-19 09:40



Étant donné une chaîne, avec un chemin python complet vers une fonction, voici comment je suis arrivé à obtenir le résultat de cette 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()

65
2017-10-16 00:24



La réponse (j'espère) personne n'a jamais voulu

Comportement semblable à l'éval

getattr(locals().get("foo") or globals().get("foo"), "bar")()

Pourquoi ne pas ajouter l'importation automatique

getattr(
    locals().get("foo") or 
    globals().get("foo") or
    __import__("foo"), 
"bar")()

Dans le cas où nous aurions des dictionnaires supplémentaires, nous voulons vérifier

getattr(next((x for x in (f("foo") for f in 
                          [locals().get, globals().get, 
                           self.__dict__.get, __import__]) 
              if x)),
"bar")()

Nous devons aller plus loin

getattr(next((x for x in (f("foo") for f in 
              ([locals().get, globals().get, self.__dict__.get] +
               [d.get for d in (list(dd.values()) for dd in 
                                [locals(),globals(),self.__dict__]
                                if isinstance(dd,dict))
                if isinstance(d,dict)] + 
               [__import__])) 
        if x)),
"bar")()

31
2018-04-09 10:17



La meilleure réponse selon le FAQ sur la programmation Python serait:

functions = {'myfoo': foo.bar}

mystring = 'myfoo'
if mystring in functions:
    functions[mystring]()

Le principal avantage de cette technique est que les chaînes n'ont pas besoin de correspondre aux noms des fonctions. C'est aussi la principale technique utilisée pour émuler une construction de cas


28
2017-10-24 13:20