une - return python




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

Quel est le meilleur moyen d'appeler une fonction à l'aide d'une chaîne portant le nom de la fonction dans un programme Python. Par exemple, disons que j'ai un module foo et une chaîne dont le contenu est "bar" . Quel est le meilleur moyen d'appeler foo.bar() ?

Je dois obtenir la valeur de retour de la fonction, c'est pourquoi je n'utilise pas simplement eval . J'ai découvert comment le faire en utilisant eval pour définir une fonction temporaire qui renvoie le résultat de cet appel de fonction, mais j'espère qu'il existe un moyen plus élégant de le faire.


Étant donné une chaîne, avec un chemin d'accès complet à une fonction en python, voici comment je me suis procuré pour 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()

C'est une réponse simple, cela vous permettra d'effacer l'écran par exemple. Il y a deux exemples ci-dessous, avec eval et exec, qui afficheront 0 en haut après le nettoyage (si vous utilisez Windows, changez en clear , cls , les utilisateurs de Linux et Mac laissent tel quel, par exemple) ou exécutez-le, respectivement.

eval("os.system(\"clear\")")
exec("os.system(\"clear\")")

En supposant que module foo avec la bar méthode:

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

Vous pouvez raccourcir les lignes 2 et 3 pour:

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

si cela est plus logique pour votre cas d'utilisation.

Vous pouvez utiliser getattr de cette manière sur des méthodes liées à une instance de classe, des méthodes au niveau du module, des méthodes de classe, etc. La liste est getattr .


Essaye ça. Bien que cela utilise encore eval, il ne l'utilise que pour appeler la fonction à partir du contexte actuel . Ensuite, vous avez la vraie fonction à utiliser comme vous le souhaitez.

Le principal avantage pour moi est que vous obtiendrez toutes les erreurs liées à l'évaluation au moment de la convocation de la fonction. Ensuite, vous ne recevrez que 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)

La meilleure réponse selon la 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 ne doivent pas nécessairement correspondre aux noms des fonctions. C’est aussi la technique principale utilisée pour émuler une construction de cas.


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

Eval comme comportement

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

Si nous avons 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")()

Pour ce que cela vaut, si vous deviez transmettre le nom de la fonction (ou de la classe) et le nom de l'application sous forme de chaîne, vous pouvez le faire:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)

rien de ce qui a été suggéré ne m'a aidé. J'ai découvert cela cependant.

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

J'utilise python 2.66

J'espère que cela t'aides





object