2396 Stimmen

Aufruf einer Funktion eines Moduls mit Hilfe seines Namens (einer Zeichenkette)

Was ist der beste Weg, um eine Funktion aufzurufen, wenn man eine Zeichenkette mit dem Namen der Funktion in einem Python-Programm hat. Nehmen wir zum Beispiel an, dass ich ein Modul habe foo und ich habe eine Zeichenkette mit folgendem Inhalt "bar" . Wie kann ich am besten anrufen? foo.bar() ?

Ich muss den Rückgabewert der Funktion erhalten, weshalb ich nicht einfach eval . Ich habe herausgefunden, wie man das macht, indem man 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.

8 Stimmen

Die Verwendung von eval würde wahrscheinlich einige Sicherheitsbedenken aufwerfen!

23 Stimmen

Zu Ihrer Information: Das Sprachmerkmal des Zugriffs auf Felder, Klassen und Methoden durch dynamische Namen heißt Reflexion . Das könnte die künftige Suche erleichtern.

2873voto

Patrick Johnmeyer Punkte 28962

Angenommenes Modul foo mit Methode bar :

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

Sie könnten die Zeilen 2 und 3 kürzen zu:

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

wenn dies für Ihren Anwendungsfall sinnvoller ist.

Sie können verwenden getattr auf diese Weise auf klasseninstanzgebundene Methoden, Methoden auf Modulebene, Klassenmethoden... die Liste geht weiter.

20 Stimmen

Hasattr oder getattr können verwendet werden, um festzustellen, ob eine Funktion definiert ist. Ich hatte eine Datenbankzuordnung (eventType und handling functionName) und wollte sicherstellen, dass ich nie "vergesse", einen Event-Handler in meinem Python zu definieren

15 Stimmen

Dies funktioniert, wenn Sie den Namen des Moduls bereits kennen. Wenn Sie jedoch möchten, dass der Benutzer den Modulnamen als Zeichenkette angibt, wird dies nicht funktionieren.

13 Stimmen

Wenn Sie eine NoneType is not callable-Ausnahme vermeiden müssen, können Sie auch die Drei-Argument-Form von getattr verwenden: getattr(foo, 'bar', lambda: None). Ich entschuldige mich für die Formatierung; die Android-App von Stackexchange ist anscheinend schrecklich.

756voto

sastanin Punkte 38556
locals()["myfunction"]()

oder

globals()["myfunction"]()

Einheimische gibt ein Wörterbuch mit einer aktuellen lokalen Symboltabelle zurück. Globale gibt ein Wörterbuch mit der globalen Symboltabelle zurück.

92 Stimmen

Diese Methode mit Globals/Locals eignet sich gut, wenn die aufzurufende Methode in demselben Modul definiert ist, aus dem der Aufruf erfolgt.

1 Stimmen

@Joelmob gibt es eine andere Möglichkeit, ein Objekt per String aus dem Root-Namensraum zu erhalten?

1 Stimmen

@NickT Ich kenne nur diese Methoden, ich glaube nicht, dass es noch andere gibt, die dieselbe Funktion erfüllen wie diese, zumindest fällt mir kein Grund ein, warum es mehr geben sollte.

469voto

HS. Punkte 14636

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

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

103 Stimmen

Die letzte Bemerkung verstehe ich nicht. __import__ hat ein eigenes Recht und der nächste Satz in den erwähnten Dokumenten sagt: "Direkte Verwendung von __import__() ist selten, außer in Fällen, in denen Sie ein Modul importieren wollen, dessen Name erst zur Laufzeit bekannt ist". Also: +1 für die gegebene Antwort.

65 Stimmen

Verwenden Sie importlib.import_module . Die offiziellen Dokumente sagen über __import__ : "Dies ist eine fortgeschrittene Funktion, die im Gegensatz zu importlib.import_module() in der alltäglichen Python-Programmierung nicht benötigt wird." docs.python.org/2/library/functions.html#__import__

10 Stimmen

@glarrain Solange Sie damit einverstanden sind, dass nur 2.7 und höher unterstützt werden.

164voto

Sourcegeek Punkte 1499

Nur ein einfacher Beitrag. Wenn die Klasse, die wir instanziieren müssen, in der gleichen Datei ist, können wir etwas wie dieses 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()

Zum Beispiel:

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

2 Stimmen

Was passiert, wenn Sie diese Funktion innerhalb einer Klassenfunktion aufrufen?

156voto

ferrouswheel Punkte 3301

Angesichts einer Zeichenfolge, mit einem vollständigen Python-Pfad zu einer Funktion, das ist, wie ich ging über das Ergebnis der besagten Funktion zu 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()

4 Stimmen

Das hat mir geholfen. Es ist eine leichtgewichtige Version von __import__ Funktion.

5 Stimmen

Ich denke, das war die beste Antwort.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X