2010-02-09 9 views
16

So habe ich eine Reihe von Klassen und eine Zeichenfolge mit einem der Klassennamen. Wie instanziiere ich eine Klasse basierend auf dieser Zeichenfolge?Instanziieren Sie eine Python-Klasse aus einem Namen

class foo: 
    def __init__(self, left, right): 
    self.left = left 
    self.right = right 

str = "foo" 
x = Init(str, A, B) 

Ich möchte x eine Instanziierung der Klasse foo sein.

+2

Duplizieren. http://stackoverflow.com/questions/734970/python-reference-to-a-class-from-a-string, http://stackoverflow.com/questions/1176136/convert-string-to-python-class- Objekt, http://stackoverflow.com/questions/553784/can-you-use-a-string-to-instantiate-a-class-in-python, etc. –

Antwort

13

Wenn Sie die Namespace beteiligt wissen, können Sie es direkt nutzen können - zum Beispiel, wenn alle Klassen in Modul sind zap, das Wörterbuch vars(zap) ist, dass Namespace; Wenn sie alle im aktuellen Modul sind, ist globals() wahrscheinlich der handlichste Weg, um dieses Wörterbuch zu bekommen.

Wenn sich die Klassen nicht alle im selben Namespace befinden, dann ist das Erstellen eines "künstlichen" Namespace (ein dict mit Klassennamen als Schlüssel und Klassenobjekte als Werte), wie @Ignacio nahelegt, wahrscheinlich der einfachste Ansatz.

6
classdict = {'foo': foo} 

x = classdict['foo'](A, B) 
+2

Wie kann ich es mit Reflektion tun? – klynch

+0

Sie * könnten * 'getattr()' verwenden, aber das könnte Sie mit Sicherheitsproblemen konfrontieren. Wenn Sie einen Klassen-Decorator verwenden, können Sie Klassen automatisch aufzählen, aber diese existieren nur in neueren Versionen von Python. –

+0

Wie würden Sie den Dekorateur verwenden?Würde es an eine Liste von instanziierbaren Klassen angehängt - und ich müsste diese Liste durchlaufen, um die richtige Klasse für die Instantiierung auszuwählen? –

15

In Ihrem Fall Sie so etwas wie

get_class = lambda x: globals()[x] 
c = get_class("foo") 

Und es ist noch einfacher kein get-Klasse aus dem Modul verwenden können

import somemodule 
getattr(somemodule, "SomeClass") 
2
classname = "Foo" 
foo = vars()[classname](Bar, 0, 4) 

Oder vielleicht

def mkinst(cls, *args, **kwargs): 
    try: 
     return globals()[cls](*args, **kwargs) 
    except: 
     raise NameError("Class %s is not defined" % cls) 

x = mkinst("Foo", bar, 0, 4, disc="bust") 
y = mkinst("Bar", foo, batman="robin") 

Verschiedene Hinweise auf das Snippet:

*args und **kwargs sind spezielle Parameter in Python, bedeuten, dass sie «eine Reihe von Nicht-Schlüsselwort args» und «ein dict von Keyword Args »entsprechend.

PEP-8 (offizieller Python-Style-Guide) empfiehlt die Verwendung von cls für Klassenvariablen.

vars() gibt ein dict der im lokalen Bereich definierten Variablen zurück.

globals() gibt ein dict der Variablen zurück, die derzeit in der Umgebung außerhalb des lokalen Bereichs vorhanden sind.

1

Sie könnten Nutzung von metaclass betrachten auch:

Cls = type('foo',(), foo.__dict__) 
x = Cls(A, B) 

Doch es schafft eine ähnliche Klasse.

Verwandte Themen