2009-06-19 2 views
19

есть ли способ ссылаться на имя класса из декларации класса? пример следующим образом:Определение самоопределяющего класса в python

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

я получил метакласс, который считывает эту информацию и делают некоторые настройки, а базовый класс реализует некоторые общие вещи экономии. я хотел бы иметь возможность создавать такие рекурсивные определения, как это, но пока в моих экспериментах я не смог добиться желаемого эффекта, обычно сталкиваясь с ошибкой «План не определен». Я понимаю, что происходит, имя класса не входит в объем внутри класса.

ответ

8

я получил метакласса, который считывает эту информацию и делает некоторые настройки

Большинство структур, которые используют метаклассами обеспечивают способ решения этого. Например, Django:

subplan = ForeignKey('self') 

Google App Engine:

subplan = SelfReferenceProperty() 

Проблема с решениями, как лавировать дополнительное свойство позже или с помощью __new__ является то, что большинство ORM метаклассы ожидают свойства класса существовать в то время, когда класс создается.

+1

Отлично, что вы упомянули Google App Engine, а также! +1 –

+1

В Google App Engine - это DB, но NDB этого не делает. Чтобы посмотреть, как это сделать в NDB, смотрите здесь: http://stackoverflow.com/questions/3531936/selfreferenceproperty-question – Brad

22

Попробуйте это:

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

Plan.subPlan = ReferenceField(Plan) 

ИЛИ использовать __new__ так:

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

удивительный, это делает именно то, что я хочу, и его не громоздкий взлом. все еще пытаясь обернуть голову вокруг всей этой динамичной вещи, haha ​​ – pedlar

0

Нет, вы не можете сделать это. Подумайте о том, что произойдет, если вы сделали это:

OtherPlan = Plan 
other_plan = OtherPlan() 

В конкретизации other_plan, что имя класса?

В любом случае, этот вид лучше всего сделать в методе __new__, который принимает параметр cls, относящийся к классу.

1

Я понимаю, что происходит, то имени класса не в рамках внутри класса.

Не совсем. Имя класса еще не определено при определении его содержимого (например, области).

Смежные вопросы