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

Quelle est la meilleure façon d'appeler une fonction donnée par 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() ?

j'ai besoin d'obtenir la valeur de retour de la fonction, c'est pourquoi je ne l'utilise pas seulement eval . J'ai compris comment le faire en utilisant eval pour définir une fonction de temp renvoie 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.

1244
demandé sur Claus Wilke 2008-08-06 07:36:08

10 réponses

, selon le module foo et la méthode bar :

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

dans la mesure où cela va, les lignes 2 et 3 peuvent être compressées comme suit:

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

si ça fait plus de sens pour votre cas d'utilisation. Vous pouvez utiliser getattr de cette façon sur les méthodes liées aux instances de classe, les méthodes au niveau du module, les méthodes de classe... la liste est longue.

1510
répondu Patrick Johnmeyer 2017-02-22 18:10:17
locals()["myfunction"]()

ou

globals()["myfunction"]()

locals retourne un dictionnaire avec une table courante de symboles locaux. globals retourne un dictionnaire avec une table de symboles globale.

414
répondu sastanin 2009-05-07 12:45:13

la solution de Patrick est probablement la plus propre. Si vous avez besoin de choisir dynamiquement le module ainsi, vous pouvez l'importer comme:

module = __import__('foo')
func = getattr(module, 'bar')
func()
253
répondu HS. 2017-02-22 18:08:23

une simple contribution. Si la classe que nous avons besoin d'instance 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')
86
répondu Sourcegeek 2014-09-22 21:49:18

avec une chaîne de caractères, avec un chemin python complet vers une fonction, c'est ainsi que j'ai obtenu 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()
67
répondu ferrouswheel 2013-10-16 00:24:22

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

Eval comme le comportement

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

pourquoi ne pas ajouter importation automatique

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

dans le cas où nous avons des dictionnaires supplémentaires que 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")()

il faut 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")()
33
répondu 00500005 2014-04-09 10:17:41

la meilleure réponse selon la FAQ de 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 faire correspondre les noms des fonctions. Il s'agit également de la technique principale utilisée pour émuler une construction de cas

30
répondu 2016-10-24 13:20:46

pour ce que ça vaut, si vous aviez besoin de passer le nom de la fonction (ou de la classe) et le nom de l'application comme chaîne de caractères, alors vous pourriez faire ceci:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)
19
répondu trubliphone 2012-02-14 05:55:36

rien de ce qui a été suggéré m'a aidé. J'ai fait découvrir ce bien.

<object>.__getattribute__(<string name>)(<params>)

j'utilise python 2.66

Espérons que cette aide

15
répondu Natdrip 2012-12-28 16:56:45

essayez ceci. Bien que cela utilise encore eval, il ne l'utilise que pour invoquer la fonction du contexte actuel . Ensuite, vous avez la fonction réelle à utiliser comme vous le souhaitez.

le principal avantage pour moi de ceci est que vous obtiendrez toutes les erreurs liées à eval au point d'invoquer la fonction. Ensuite, vous obtiendrez seulement les erreurs liées à la fonction lorsque vous appelez.

def say_hello(name):
    print 'Hello {}!'.format(name)

# get the function by name
method_name = 'say_hello'
method = eval(method_name)

# call it like a regular function later
args = ['friend']
kwargs = {}
method(*args, **kwargs)
14
répondu tvt173 2016-12-08 18:09:50