tags:

views:

320

answers:

4

is there any way to reference a class name from within the class declaration? an example follows:

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

i've got a metaclass that reads this information and does some setup, and the base class implements some common saving stuff. i would love to be able to create recursive definitions like this, but so far in my experimentation i have been unable to get the effect i desire, usually running into a "Plan is not defined" error. I understand what is happening, the name of the class isn't in scope inside the class.

+6  A: 

Try this:

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

Plan.subPlan = ReferenceField(Plan)

OR use __new__ like this:

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)
Evan Fosmark
awesome, this does exactly what i want it to, and its not a humongous hack. still trying to wrap my head around this whole dynamic thing, haha
pedlar
Glad I could help. ;)
Evan Fosmark
A: 

No, you can't do that. Think about what would happen if you did this:

 OtherPlan = Plan
 other_plan = OtherPlan()

At instantiation of other_plan, what is the name of the class?

Anyway, this sort of thing is best done in the __new__ method, which takes a cls parameter referring to the class.

Daniel Roseman
A: 

I understand what is happening, the name of the class isn't in scope inside the class.

Not exactly. The name of the class is not yet defined when defining it's contents (e.g. scope).

Piotr Findeisen
+3  A: 

i've got a metaclass that reads this information and does some setup

Most frameworks that use metaclasses provide a way to resolve this. For instance, Django:

subplan = ForeignKey('self')

Google App Engine:

subplan = SelfReferenceProperty()

The problem with solutions like tacking an additional property on later or using __new__ is that most ORM metaclasses expect the class properties to exist at the time when the class is created.

Miles
Great that you mentioned Google App Engine as well! +1
Gergely Orosz