Tengo la necesidad de tomar un argumento de cadena y crear un objeto de la clase nombrada en esa cadena en Python. En Java, usaría Class.forName().newInstance()
. ¿Existe un equivalente en Python?
Gracias por las respuestas. Para responder a aquellos que quieren saber lo que estoy haciendo: quiero usar un argumento de línea de comando como nombre de clase y crear una instancia. De hecho, estoy programando en Jython y creando instancias de clases de Java, de ahí el carácter Java de la pregunta. getattr()
Funciona genial. Muchas gracias.
java
python
class
instantiation
Jason
fuente
fuente
importlib.import
, que se exportó de python 3 a 2.7 ( docs.python.org/2/library/importlib.html )Respuestas:
La reflexión en Python es mucho más fácil y flexible que en Java.
Recomiendo leer este tutorial
No hay una función directa (que yo sepa) que toma un nombre de clase totalmente calificado y devuelve la clase, sin embargo, tiene todas las piezas necesarias para construir eso y puede conectarlas.
Sin embargo, un pequeño consejo: no intente programar en estilo Java cuando esté en Python.
Si puede explicar qué es lo que está tratando de hacer, tal vez podamos ayudarlo a encontrar una forma más pitónica de hacerlo.
Aquí hay una función que hace lo que quieres:
Puede utilizar el valor de retorno de esta función como si fuera la propia clase.
Aquí tienes un ejemplo de uso:
¿Cómo funciona?
Estamos usando
__import__
para importar el módulo que contiene la clase, lo que requería que primero extrajáramos el nombre del módulo del nombre completo. Luego importamos el módulo:En este caso,
m
solo hará referencia al módulo de nivel superior,Por ejemplo, si su clase vive en el
foo.baz
módulo, entoncesm
será el módulo.foo
Podemos obtener fácilmente una referencia para
foo.baz
usargetattr( m, 'baz' )
Para pasar del módulo de nivel superior a la clase, debe usar de forma recursiva
gettatr
en las partes del nombre de la claseDigamos, por ejemplo, si el nombre de su clase es,
foo.baz.bar.Model
entonces hacemos esto:Esto es lo que está sucediendo en este bucle:
Al final del ciclo,
m
habrá una referencia a la clase. Esto significa que enm
realidad es la clase en sí misma, puede hacer, por ejemplo:fuente
__import__
existe. Los proyectos como Django que hacen magia de carga de módulos lo usan todo el tiempo. Buena respuesta.get_class = lambda name: reduce(getattr, name.split('.')[1:], __import__(name.partition('.')[0]))
. Aunque 'object.from_name' podría ser un nombre mejor. Ejemplos: get_class ('decimal.Decimal'), get_class (nombre_módulo).Suponiendo que la clase está en su alcance:
De otra manera:
Editar: Tenga en cuenta que no puede dar un nombre como 'foo.bar' a getattr. Tendrá que dividirlo. y llame a getattr () en cada pieza de izquierda a derecha. Esto manejará eso:
fuente
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))
Uso
fuente
Otra implementación más.
fuente
if module_name
LBYL es bastante redudant, ya que el error que se obtiene si simplemente borrar esas líneas es:ValueError: Empty module name
.Parece que te estás acercando a esto desde el medio en lugar del principio. ¿Qué estás intentando hacer realmente? Encontrar la clase asociada con una cadena dada es un medio para lograr un fin.
Si aclara su problema, que podría requerir su propia refactorización mental, puede presentarse una mejor solución.
Por ejemplo: ¿Está intentando cargar un objeto guardado en función de su nombre de tipo y un conjunto de parámetros? Python deletrea este desencadenamiento y deberías mirar el módulo pickle . Y aunque el proceso de despegado hace exactamente lo que usted describe, no tiene que preocuparse por cómo funciona internamente:
fuente
Esto se encuentra en la biblioteca estándar de Python, como unittest.TestLoader.loadTestsFromName. Desafortunadamente, el método continúa realizando actividades adicionales relacionadas con las pruebas, pero esta primera ha parece reutilizable. Lo edité para eliminar la funcionalidad relacionada con la prueba:
fuente
Necesitaba obtener objetos para todas las clases existentes en
my_package
. Así que importar todas las clases necesarias enmy_package
's__init__.py
.Entonces mi estructura de directorio es así:
Y mi
__init__.py
aspecto es así:Luego creo una función como esta:
Dónde
module_name = 'my_package'
inspeccionar el documento: https://docs.python.org/3/library/inspect.html#inspect.getmembers
fuente