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

Translate

Quelle est la meilleure façon d'appeler une fonction à partir d'une chaîne avec le nom de la fonction dans un programme Python. Par exemple, disons que j'ai un modulefoo, et j'ai une chaîne dont le contenu est"bar". Quelle est la meilleure façon d'appelerfoo.bar()?

J'ai besoin d'obtenir la valeur de retour de la fonction, c'est pourquoi je n'utilise pas simplementeval. J'ai compris comment le faire en utilisantevalpour 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.

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Module en supposantfooavec méthodebar:

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 en:

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

si cela a plus de sens pour votre cas d'utilisation. Vous pouvez utilisergetattrde cette façon sur les méthodes liées à l'instance de classe, les méthodes au niveau du module, les méthodes de classe ... la liste est longue.

La source
Translate
locals()["myfunction"]()

or

globals()["myfunction"]()

des locauxrenvoie un dictionnaire avec une table de symboles locale courante.globauxrenvoie un dictionnaire avec une table de symboles globale.

La source
HS.
Translate

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

module = __import__('foo')
func = getattr(module, 'bar')
func()
La source
Translate

Juste une simple contribution. Si la classe que nous devons instancier 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')
La source
Translate

Étant donné une chaîne, 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()
La source
Cornelius Lee
Translate

La meilleure réponse selon leFAQ sur la programmation Pythonserait:

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 également la principale technique utilisée pour émuler une construction de cas

La source
Translate

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

Évaluez comme un 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")()

Au 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")()
La source
Translate

Pour ce que cela vaut, si vous deviez passer 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)
La source
Translate

Essaye ça. Bien que cela utilise toujours eval, il ne l'utilise que pourinvoquer 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 l'invocation de la fonction. Ensuite, vous obtiendrezseulementles 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 source
Translate

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

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

J'utilise python 2.66

J'espère que cela t'aides

La source
Translate

Comme cette questionComment appeler dynamiquement des méthodes dans une classe à l'aide de l'affectation de nom de méthode à une variable [duplicate]marqué comme un doublon comme celui-ci, je poste une réponse connexe ici:

Le scénario est qu'une méthode dans une classe souhaite appeler une autre méthode sur la même classe de manière dynamique, j'ai ajouté quelques détails à l'exemple original qui offre un scénario plus large et plus clair:

class MyClass:
    def __init__(self, i):
        self.i = i

    def get(self):
        func = getattr(MyClass, 'function{}'.format(self.i))
        func(self, 12)   # This one will work
        # self.func(12)    # But this does NOT work.


    def function1(self, p1):
        print('function1: {}'.format(p1))
        # do other stuff

    def function2(self, p1):
        print('function2: {}'.format(p1))
        # do other stuff


if __name__ == "__main__":
    class1 = MyClass(1)
    class1.get()
    class2 = MyClass(2)
    class2.get()

Sortie (Python 3.7.x)

fonction1: 12

fonction2: 12

La source
Translate

C'est une réponse simple, cela vous permettra de vider 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, changezclearàcls, Les utilisateurs Linux et Mac laissent tel quel par exemple) ou l'exécutent simplement, respectivement.

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