2008-10-21 24 views
30

Quiero saber cómo usar variables para objetos y nombres de funciones en Python. En PHP, puede hacer esto:¿Cómo usar las variables para los nombres de clase en Python?

$className = "MyClass"; 

$newObject = new $className(); 

¿Cómo se hace este tipo de cosas en Python? O, ¿no estoy apreciando por completo alguna diferencia fundamental con Python, y si es así, qué es?

+0

Me interesaría saber por qué tiene que hacer esto, creo que podría haber una manera más pitonica que no requiere nombres de clase variable. – TimB

+0

"¿No estoy apreciando totalmente alguna diferencia fundamental con Python, y si es así, qué es?" Posiblemente. ¿Por qué usa código como el ejemplo anterior? ¿Mple? Proporcione un ejemplo más grande que proporcione algún contexto. –

+0

Interesante, pero estoy de acuerdo con TimB, me gustaría escuchar el caso de uso para esto. – monkut

Respuesta

21

En Python,

className = MyClass 
newObject = className() 

La primera línea hace que la variable de className se refieren a la misma cosa que MyClass. A continuación, la siguiente línea llama al constructor MyClass a través de la variable className.

Como ejemplo concreto: (. En Python, list es el constructor de la clase list)

>>> className = list 
>>> newObject = className() 
>>> newObject 
[] 

La diferencia es que en PHP, usted representa el nombre de la clase que desea para referirse a una cadena, mientras que en Python puede hacer referencia directamente a la misma clase. Si debe usar una cadena (por ejemplo, si el nombre de la clase se crea dinámicamente), entonces deberá usar otras técnicas.

+12

downvoted, porque su solución no coincide con la de la pregunta. Lo que está buscando es crear una instancia de una clase con una cadena. – reggie

+1

Por favor, quédese con PEP8. El uso de nombres mixedCase se siente un tanto en contra de los valores que SO representa. – dcsordas

+0

De acuerdo con el primer comentario, esto no funciona para un nombre de clase almacenado en un varible – Matt

4

Si usted tiene esto:

class MyClass: 
    def __init__(self): 
     print "MyClass" 

A continuación, se suele hacer esto:

>>> x = MyClass() 
MyClass 

Pero también se puede hacer esto, que es lo que creo que está pidiendo:

>>> a = "MyClass" 
>>> y = eval(a)() 
MyClass 

Pero, ten mucho cuidado con dónde obtienes la cadena en la que utilizas "eval()", si es del usuario, eres esencialmente creadora un enorme agujero de seguridad.

Actualización: El uso de type() como se muestra en la respuesta de Coleifer es muy superior a esta solución.

+9

OMG, ¡no! La función eval es malvada. No lo uses. – ddaa

+1

Diría que es una buena regla general. –

+0

@TimB, creo que esta debería ser la mejor respuesta si es mi decisión. – Gang

47

Suponiendo que some_module tiene una clase llamada "class_name":

import some_module 
klass = getattr(some_module, "class_name") 
some_object = klass() 

deben tener en cuenta que usted debe tener cuidado aquí: convertir cadenas en código puede ser peligroso si la cadena de vino del usuario, por lo que debe tenga en cuenta la seguridad en esta situación. :)

Otro método (suponiendo que todavía estamos utilizando "class_name"):

class_lookup = { 'class_name' : class_name } 
some_object = class_lookup['class_name']() #call the object once we've pulled it out of the dict 

El último método es probablemente la forma más segura de hacer esto, por lo que es probablemente lo que se debe utilizar si al todo posible.

+0

Muy bien, estoy creando un controlador para clases dinámicas y campos dinámicos. Hice 'classes = {'class1': Class1, 'class2': Class2, ...}'. Ahora puedo obtener el objeto con 'myob = classes [')'. – Furbeenator

+0

truco genial, simple. Estaba molestando 2 horas antes de encontrar esto. Gracias. –

18

Si necesita crear una clase dinámica en Python (es deciruno cuyo nombre es una variable), puede utilizar el tipo() que toma 3 params: nombre, bases, ATTRS

>>> class_name = 'MyClass' 
>>> klass = type(class_name, (object,), {'msg': 'foobarbaz'}) 

<class '__main__.MyClass'> 

>>> inst = klass() 
>>> inst.msg 
foobarbaz 
  • Nota sin embargo, que esto no 'instantiate' del objeto (es decir, no llama constructores, etc. Crea una nueva clase (!) con el mismo nombre.
Cuestiones relacionadas