2009-06-19 16 views
19

¿Hay alguna manera de hacer referencia a un nombre de clase dentro de la declaración de clase? un ejemplo es el siguiente:Definición de clase autorreferencial en python

class Plan(SiloBase): 
    cost = DataField(int) 
    start = DataField(System.DateTime) 
    name = DataField(str) 
    items = DataCollection(int) 
    subPlan = ReferenceField(Plan) 

tengo un metaclase que lee esta información y hace algo de la configuración y la clase base implementa un poco de materia de ahorro común. Me encantaría poder crear definiciones recursivas como esta, pero hasta ahora en mi experimentación no he podido obtener el efecto que deseo, usualmente corriendo hacia un error "El plan no está definido". Entiendo lo que está sucediendo, el nombre de la clase no está dentro del alcance dentro de la clase.

Respuesta

8

Tengo una metaclase que lee esta información y hace algunos configuración

mayoría de los marcos que utilizan metaclases proporcionan una manera de resolver esto. Por ejemplo, Django:

subplan = ForeignKey('self') 

Google App Engine:

subplan = SelfReferenceProperty() 

El problema con soluciones como viradas una propiedad adicional en la tarde o el uso de __new__ es que la mayoría metaclases ORM esperan que las propiedades de la clase que existan en el momento la clase es creada.

+1

¡Es fantástico que hayas mencionado a Google App Engine también! +1 –

+1

En Google App Engine, DB tiene esto, pero NDB no. Para ver cómo hacer esto en NDB mira aquí: http://stackoverflow.com/questions/3531936/selfreferenceproperty-question – Brad

22

Prueba esto:

class Plan(SiloBase): 
    cost = DataField(int) 
    start = DataField(System.DateTime) 
    name = DataField(str) 
    items = DataCollection(int) 

Plan.subPlan = ReferenceField(Plan) 

o uso __new__ así:

class Plan(SiloBase): 

    def __new__(cls, *args, **kwargs): 
     cls.cost = DataField(int) 
     cls.start = DataField(System.DateTime) 
     cls.name = DataField(str) 
     cls.items = DataCollection(int) 
     cls.subPlan = ReferenceField(cls) 
     return object.__new__(cls, *args, **kwargs) 
+0

impresionante, esto hace exactamente lo que quiero, y no es un hack enorme. todavía estoy tratando de entender todo este aspecto dinámico, jaja – pedlar

0

No, usted no puede hacer eso. Pensar en lo que sucedería si se hizo esto:

OtherPlan = Plan 
other_plan = OtherPlan() 

A instancia de other_plan, ¿cuál es el nombre de la clase?

De todos modos, este tipo de cosas se realiza mejor en el método __new__, que toma un parámetro cls que hace referencia a la clase.

1

entiendo lo que está pasando, el nombre de la clase no está en el ámbito dentro de la clase.

No exactamente. El nombre de la clase aún no está definido al definir su contenido (por ejemplo, el alcance).

Cuestiones relacionadas