2010-02-09 24 views
16

Así que tengo un conjunto de clases y una cadena con uno de los nombres de clase. ¿Cómo instanciar una clase basada en esa cadena?Crear una instancia de una clase Python a partir de un nombre

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

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

Quiero que x sea una instanciación de la clase foo.

+2

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

Respuesta

13

Si conoce el espacio de nombres involucrados, se puede utilizar directamente - por ejemplo, si todas las clases son en el módulo zap, el diccionario vars(zap) es ese espacio de nombres; si están todos en el módulo actual, globals() es probablemente la forma más práctica de obtener ese diccionario.

Si las clases no están todas en el mismo espacio de nombres, construir un espacio de nombre "artificial" (un dict dedicado con nombres de clase como claves y objetos de clase como valores), como sugiere @Ignacio, es probablemente el enfoque más simple.

6
classdict = {'foo': foo} 

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

¿Cómo puedo hacerlo utilizando la reflexión? – klynch

+0

Usted * podría * usar 'getattr()', pero eso podría exponerlo a problemas de seguridad. El uso de un decorador de clases le permitirá enumerar clases automáticamente, pero esas solo existen en las versiones más nuevas de Python. –

+0

¿Cómo usarías el decorador?¿Se agregaría a una lista de clases instanciables, y tendría que repetir en esta lista para elegir la clase correcta para crear instancias? –

15

En su caso se puede usar algo como

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

Y es aún más fácil de ninguna clase llegar desde el módulo de

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

O quizás

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

notas varias sobre el fragmento:

*args y **kwargs son parámetros especiales en Python, que significan «una serie de argumentos no de palabras clave» y «un diccionario de palabras clave args »en consecuencia.

PEP-8 (guía de estilo oficial de Python) recomienda usar cls para las variables de clase.

vars() devuelve un dict de variables definidas en el ámbito local.

globals() devuelve un dict de variables actualmente presentes en el entorno fuera del ámbito local.

1

Usted podría considerar el uso de metaclase así:

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

Sin embargo, crea otra clase similar.

Cuestiones relacionadas