Ich muss ein String-Argument nehmen und ein Objekt der Klasse erstellen, die in diesem String in Python genannt wird. In Java würde ich verwenden Class.forName().newInstance()
. Gibt es ein Äquivalent in Python?
Danke für die Antworten. Um diejenigen zu beantworten, die wissen möchten, was ich tue: Ich möchte ein Befehlszeilenargument als Klassennamen verwenden und es instanziieren. Ich programmiere tatsächlich in Jython und instanziiere Java-Klassen, daher die Java-Ness der Frage. getattr()
funktioniert super. Vielen Dank.
java
python
class
instantiation
Jason
quelle
quelle
importlib.import
, die von Python 3 auf 2.7 ( docs.python.org/2/library/importlib.html ) zurückportiert wurdeAntworten:
Die Reflexion in Python ist viel einfacher und flexibler als in Java.
Ich empfehle dieses Tutorial zu lesen
Es gibt keine direkte Funktion (die ich kenne), die einen vollständig qualifizierten Klassennamen annimmt und die Klasse zurückgibt. Sie haben jedoch alle Teile, die zum Erstellen erforderlich sind, und können sie miteinander verbinden.
Ein Tipp: Versuchen Sie nicht, im Python-Stil zu programmieren, wenn Sie in Python sind.
Wenn Sie erklären können, was Sie versuchen, können wir Ihnen vielleicht helfen, einen pythonischeren Weg zu finden.
Hier ist eine Funktion, die macht, was Sie wollen:
Sie können den Rückgabewert dieser Funktion so verwenden, als wäre es die Klasse selbst.
Hier ist ein Anwendungsbeispiel:
Wie funktioniert das?
Wir verwenden
__import__
das Modul, das die Klasse enthält. Daher müssen wir zuerst den Modulnamen aus dem vollständig qualifizierten Namen extrahieren. Dann importieren wir das Modul:In diesem Fall
m
bezieht sich nur auf das Modul der obersten Ebene,Wenn Ihre Klasse beispielsweise im
foo.baz
Modul lebt , istm
dies das Modul.foo
Wir können leicht einen Verweis auf die
foo.baz
Verwendung erhaltengetattr( m, 'baz' )
Um vom Modul der obersten Ebene zur Klasse zu gelangen, müssen
gettatr
die Teile des Klassennamens rekursiv verwendet werdenSagen
foo.baz.bar.Model
wir zum Beispiel, wenn Ihr Klassenname lautet, machen wir Folgendes:Folgendes passiert in dieser Schleife:
Am Ende der Schleife
m
wird ein Verweis auf die Klasse angezeigt. Dies bedeutet, dassm
es sich tatsächlich um die Klasse selbst handelt, die Sie beispielsweise ausführen können:quelle
__import__
es. Projekte wie Django, die Modul-Lade-Magie betreiben, verwenden sie ständig. Gute Antwort.get_class = lambda name: reduce(getattr, name.split('.')[1:], __import__(name.partition('.')[0]))
. Obwohl 'object.from_name' ein besserer Name sein könnte. Beispiele: get_class ('decimal.Decimal'), get_class (Modulname).Angenommen, die Klasse liegt in Ihrem Geltungsbereich:
Andernfalls:
Bearbeiten: Beachten Sie, dass Sie getattr keinen Namen wie 'foo.bar' geben können. Sie müssen es durch teilen. und rufe getattr () für jedes Stück von links nach rechts auf. Dies wird das erledigen:
quelle
attrs = 'foo.bar.baz'.split('.'); fooBar = reduce(getattr, attrs[1:], __import__(attrs[0]))
module, _, attrs = 'foo.bar.baz'.partition('.'); fooBar = reduce(getattr, attrs, __import__(module))
Verwendung
quelle
Noch eine Implementierung.
quelle
if module_name
LBYL ist ziemlich redundant, da der Fehler, den Sie erhalten, wenn Sie diese Zeilen einfach löschen, ist :ValueError: Empty module name
.Es scheint, dass Sie sich dem von der Mitte anstatt von Anfang an nähern. Was versuchst du wirklich zu tun? Das Finden der Klasse, die einer bestimmten Zeichenfolge zugeordnet ist, ist ein Mittel zum Zweck.
Wenn Sie Ihr Problem klären, was möglicherweise Ihr eigenes mentales Refactoring erfordert, bietet sich möglicherweise eine bessere Lösung an.
Zum Beispiel: Versuchen Sie, ein gespeichertes Objekt basierend auf seinem Typnamen und einer Reihe von Parametern zu laden? Python buchstabiert dieses Unpickling und Sie sollten sich das Pickle-Modul ansehen . Und obwohl der Aufhebungsprozess genau das tut, was Sie beschreiben, müssen Sie sich keine Gedanken darüber machen, wie er intern funktioniert:
quelle
Dies befindet sich in der Python-Standardbibliothek als unittest.TestLoader.loadTestsFromName. Leider führt die Methode zusätzliche testbezogene Aktivitäten durch, aber diese erste Version scheint wiederverwendbar zu sein. Ich habe es bearbeitet, um die testbezogene Funktionalität zu entfernen:
quelle
Ich musste Objekte für alle vorhandenen Klassen in bekommen
my_package
. Also importiere ich alle notwendigen Klassen inmy_package
's__init__.py
.Meine Verzeichnisstruktur sieht also so aus:
Und mein
__init__.py
sieht so aus:Dann erstelle ich eine Funktion wie folgt:
Wo
module_name = 'my_package'
Überprüfen Sie das Dokument: https://docs.python.org/3/library/inspect.html#inspect.getmembers
quelle