python中的自引用类定义

时间:2020-12-01 18:09:44

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.

我有一个读取此信息的元类并进行一些设置,基类实现了一些常见的保存。我希望能够创建这样的递归定义,但到目前为止,在我的实验中,我无法获得我想要的效果,通常会遇到“计划未定义”错误。我理解发生了什么,类的名称不在类的范围内。

4 个解决方案

#1


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:

大多数使用元类的框架都提供了解决此问题的方法。例如,Django:

subplan = ForeignKey('self')

Google App Engine:

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.

稍后使用__new__添加附加属性等解决方案的问题是,大多数ORM元类都希望在创建类时存在类属性。

#2


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:

或者像这样使用__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)

#3


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).

不完全是。在定义类的内容(例如范围)时,尚未定义类的名称。

#4


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?

在other_plan的实例化中,该类的名称是什么?

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

无论如何,这种事情最好在__new__方法中完成,它接受一个引用该类的cls参数。

#1


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:

大多数使用元类的框架都提供了解决此问题的方法。例如,Django:

subplan = ForeignKey('self')

Google App Engine:

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.

稍后使用__new__添加附加属性等解决方案的问题是,大多数ORM元类都希望在创建类时存在类属性。

#2


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:

或者像这样使用__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)

#3


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).

不完全是。在定义类的内容(例如范围)时,尚未定义类的名称。

#4


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?

在other_plan的实例化中,该类的名称是什么?

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

无论如何,这种事情最好在__new__方法中完成,它接受一个引用该类的cls参数。