Frage Aufruf einer Funktion eines Moduls unter Verwendung seines Namens (eine Zeichenkette)


Was ist der beste Weg, um eine Funktion mit einem String mit dem Namen der Funktion in einem Python-Programm aufzurufen. Nehmen wir zum Beispiel an, dass ich ein Modul habe foo, und ich habe eine Zeichenfolge, deren Inhalt ist "bar". Was ist der beste Weg, um anzurufen? foo.bar()?

Ich muss den Rückgabewert der Funktion bekommen, weshalb ich nicht nur verwende eval. Ich habe herausgefunden, wie ich es benutze eval um eine temporäre Funktion zu definieren, die das Ergebnis dieses Funktionsaufrufs zurückgibt, aber ich hoffe, dass es einen eleganteren Weg gibt, dies zu tun.


1185
2017-08-06 03:36


Ursprung


Antworten:


Angenommenes Modul foo mit Methode bar:

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

Soweit dies möglich ist, können die Zeilen 2 und 3 komprimiert werden auf:

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

wenn das für Ihren Anwendungsfall sinnvoller ist. Sie können verwenden getattr Auf diese Weise an Klasseninstanz-gebundenen Methoden, Modulebenen-Methoden, Klassenmethoden ... geht die Liste weiter.


1439
2017-08-06 03:57



locals()["myfunction"]()

oder

globals()["myfunction"]()

Einheimische Gibt ein Wörterbuch mit einer aktuellen lokalen Symboltabelle zurück. Globals gibt ein Dictionary mit globaler Symboltabelle zurück.


401
2018-05-07 12:45



Patricks Lösung ist wahrscheinlich die sauberste. Wenn Sie das Modul auch dynamisch aufnehmen müssen, können Sie es wie folgt importieren:

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

240
2017-08-07 11:35



Nur ein einfacher Beitrag. Wenn sich die Klasse, die wir instanzieren müssen, in derselben Datei befindet, können wir Folgendes verwenden:

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

Beispielsweise:

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')

Und wenn nicht eine Klasse:

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

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

81
2017-08-19 09:40



Wenn ich eine Zeichenfolge mit einem vollständigen Python-Pfad zu einer Funktion angegeben habe, habe ich das Ergebnis dieser Funktion erhalten:

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



Die Antwort (ich hoffe) hat niemand jemals gewollt

Eval wie Verhalten

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

Warum nicht automatisch importieren?

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

Falls wir zusätzliche Wörterbücher haben, die wir überprüfen möchten

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

Wir müssen tiefer gehen

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



Die beste Antwort nach dem Python-Programmierung FAQ wäre:

functions = {'myfoo': foo.bar}

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

Der Hauptvorteil dieser Technik besteht darin, dass die Zeichenfolgen nicht mit den Namen der Funktionen übereinstimmen müssen. Dies ist auch die primäre Technik, die zum Emulieren eines Fallkonstrukts verwendet wird


28
2017-10-24 13:20



Was es wert ist, wenn Sie den Namen der Funktion (oder Klasse) und den Namen der App als Zeichenfolge übergeben müssen, können Sie Folgendes tun:

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

18
2018-02-14 05:55