Ich muss dynamisch eine Instanz einer Klasse in Python erstellen. Grundsätzlich verwende ich das Modul load_module und inspect, um die Klasse in ein Klassenobjekt zu importieren und zu laden, aber ich kann nicht herausfinden, wie eine Instanz dieses Klassenobjekts erstellt wird.
Bitte helfen Sie!
instance = Class()
...Antworten:
Ich fand die Antwort auf die Frage heraus, die mich auf diese Seite gebracht hatte. Da niemand die Antwort auf meine Frage vorgeschlagen hat, dachte ich, ich würde sie posten.
class k: pass a = k() k2 = a.__class__ a2 = k2()
Zu diesem Zeitpunkt sind a und a2 beide Instanzen derselben Klasse (Klasse k).
quelle
a3 = k2(7)
k2 = a.__class__
undk2 = k
?k2
Ist der Objekttyp, in diesem Fall de Typ vona
(a.__class
),k2()
erstellen Sie eine neue Instanz eines Objekts dieses Typs unabhängig vona
.k2 = k
würde einfach einen neuen Verweis auf dieselbe Instanz erstellen.class
Objekt auch mitk2 = type(a)
abrufen und dann das Klassenobjekt aufrufena2 = k2()
. Es ist im Grunde das gleiche, aber Sie müssen Ihren Code nicht mit diesen hässlichen doppelten Unterstrichen verunreinigen ... könnte auch portabler seinRufen Sie einfach den eingebauten "Typ" mit drei Parametern auf:
ClassName = type("ClassName", (Base1, Base2,...), classdictionary)
Update wie im Kommentar unten angegeben. Dies ist überhaupt nicht die Antwort auf diese Frage. Ich werde es nicht löschen, da es Hinweise gibt, die einige Leute hier bekommen, die versuchen, dynamisch Klassen zu erstellen - was die obige Zeile tut.
Um ein Objekt einer Klasse zu erstellen, hat man auch eine Referenz, wie in der akzeptierten Antwort angegeben, man muss nur die Klasse aufrufen:
Der Mechanismus für die Instanziierung ist also:
Python verwendet nicht das
new
Schlüsselwort, das einige Sprachen verwenden. Stattdessen erklärt das Datenmodell den Mechanismus, der zum Erstellen einer Instanz einer Klasse verwendet wird, wenn diese mit derselben Syntax wie alle anderen aufrufbaren aufgerufen wird:Die
__call__
Methode der Klasse wird aufgerufen (im Fall einer Klasse ist ihre Klasse die "Metaklasse" - normalerweise die integriertetype
). Das normale Verhalten dieses Aufrufs besteht darin, die (pseudo) statische__new__
Methode für die zu instanziierende Klasse aufzurufen , gefolgt von ihrer__init__
. Das__new__
Verfahren ist verantwortlich für die Zuteilung von Speicher und so, und in der Regel wird durch die durchgeführt__new__
vonobject
dem die Klassenhierarchie Wurzel.So ruft
ClassObject()
aufruftClassObject.__class__.call()
(die in der Regel wirdtype.__call__
) diese__call__
Methode classobject selbst als ersten Parameter erhalten - eine reine Python - Implementierung würde so aussehen: (die CPython Version ist natürlich in C durchgeführt und mit vielen zusätzlichen Code für cornercases und Optimierungen)class type: ... def __call__(cls, *args, **kw): constructor = getattr(cls, "__new__") instance = constructor(cls) if constructor is object.__new__ else constructor(cls, *args, **kw) instance.__init__(cls, *args, **kw) return instance
(Ich erinnere mich nicht, dass ich in den Dokumenten die genaue Rechtfertigung (oder den Mechanismus) für die Unterdrückung zusätzlicher Parameter an die Wurzel
__new__
und die Weitergabe an andere Klassen gesehen habe - aber es ist das, was "im wirklichen Leben" passiert - wennobject.__new__
es mit zusätzlichen Parametern aufgerufen wird löst einen Typfehler aus - jede benutzerdefinierte Implementierung von a__new__
erhält jedoch normalerweise die zusätzlichen Parameter.quelle
Auf diese Weise können Sie dynamisch eine
Child
in Ihrem Code benannte Klasse erstellen, sofern dieseParent
bereits vorhanden ist. Auch wenn Sie keine expliziteParent
Klasse haben, können Sieobject
...Der folgende Code definiert ihn
__init__()
und ordnet ihn dann der Klasse zu.>>> child_name = "Child" >>> child_parents = (Parent,) >>> child body = """ def __init__(self, arg1): # Initialization for the Child class self.foo = do_something(arg1) """ >>> child_dict = {} >>> exec(child_body, globals(), child_dict) >>> childobj = type(child_name, child_parents, child_dict) >>> childobj.__name__ 'Child' >>> childobj.__bases__ (<type 'object'>,) >>> # Instantiating the new Child object... >>> childinst = childobj() >>> childinst <__main__.Child object at 0x1c91710> >>>
quelle
Wenn Sie ein Modul mit einer Klasse haben, die Sie importieren möchten, können Sie dies folgendermaßen tun.
Wenn Sie nicht wissen, wie die Klasse heißt, können Sie die in einem Modul verfügbaren Klassen durchlaufen.
import inspect module = __import__(filename) for c in module.__dict__.values(): if inspect.isclass(c): # You may need do some additional checking to ensure # it's the class you want instance = c()
quelle