Самостоятельная ссылка на определение класса в python - PullRequest
19 голосов
/ 20 июня 2009

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

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

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

Ответы [ 4 ]

23 голосов
/ 20 июня 2009

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

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)
8 голосов
/ 20 июня 2009

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

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

subplan = ForeignKey('self')

Google App Engine :

subplan = SelfReferenceProperty()

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

2 голосов
/ 20 июня 2009

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

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

0 голосов
/ 20 июня 2009

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

 OtherPlan = Plan
 other_plan = OtherPlan()

При создании экземпляра other_plan как называется класс?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...