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

voix
1k

Quelle est la meilleure façon de s'y prendre pour appeler une fonction d' 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 bar. Quelle est la meilleure façon d'aller à appeler foo.bar()?

Je dois obtenir la valeur de retour de la fonction, ce qui est la raison pour laquelle je ne suis pas juste utiliser eval. Je me suis dit comment le faire en utilisant evalpour définir une fonction de température qui renvoie le résultat de cet appel de fonction, mais j'espère qu'il ya une façon de le faire plus élégant.

Créé 06/08/2008 à 04:36
source utilisateur
Dans d'autres langues...                            


10 réponses

voix
1k

Module supposant fooavec la méthode bar:

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

En ce qui concerne ce qui va, les lignes 2 et 3 peuvent être compressés à:

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

si cela fait plus de sens pour votre cas d'utilisation. Vous pouvez utiliser getattrce mode sur instance de classe des méthodes, des méthodes liées au niveau du module, les méthodes de classe ... la liste est longue.

Créé 06/08/2008 à 04:57
source utilisateur

voix
387
locals()["myfunction"]()

ou

globals()["myfunction"]()

les habitants retourne un dictionnaire avec une table de symbole local actuel. globals retourne un dictionnaire avec table de symbole global.

Créé 07/05/2009 à 13:45
source utilisateur

voix
229

La solution de Patrick est probablement la plus propre. Si vous devez dynamiquement prendre le module ainsi, vous pouvez l'importer comme:

module = __import__('foo')
func = getattr(module, 'bar')
func()
Créé 07/08/2008 à 12:35
source utilisateur

voix
77

Juste un simple contribution. Si la classe que nous devons par exemple 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, sinon une classe:

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

globals()['sampleFunc']('sample arg')
Créé 19/08/2012 à 10:40
source utilisateur

voix
64

D'une chaîne, avec un chemin de python complet à une fonction, voilà comment je suis allé à 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()
Créé 16/10/2013 à 01:24
source utilisateur

voix
30

La réponse (je l'espère) n'a jamais voulu

Eval comme le comportement

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

Pourquoi ne pas ajouter l'auto-importation

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")()

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")()
Créé 09/04/2014 à 11:17
source utilisateur

voix
26

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 ne doivent pas nécessairement correspondre aux noms des fonctions. Ceci est également la principale technique utilisée pour émuler une construction de cas

Créé 24/10/2016 à 13:20
source utilisateur

voix
18

Pour ce que ça vaut, si vous avez besoin de passer la fonction (ou classe) nom et nom de l'application comme une chaîne, vous pouvez le faire:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)
Créé 14/02/2012 à 06:55
source utilisateur

voix
15

Essaye ça. Bien que cela utilise encore eval, il ne l' utilise que pour appeler la fonction du contexte actuel . , Vous avez la fonction réelle à utiliser comme vous le souhaitez ensuite.

Le principal avantage pour moi de tout cela est que vous obtiendrez des erreurs liées eval-au point d'appeler la fonction. Ensuite , vous obtiendrez uniquement 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)
Créé 07/12/2016 à 18:29
source utilisateur

voix
13

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

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

J'utilise python 2,66

J'espère que cela t'aides

Créé 28/12/2012 à 17:56
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more