Self Referencing Class Definition in python

Sine Python 3.7 and PEP 563 there's a way to do that.

Add the import

from __future__ import annotations

and the following code will work

from __future__ import annotations
from typing import List

class Refer(object):
    def __init__(self, x: Plan):
        self.x: Plan = x

class Plan(object):
    def __init__(self):
        pass
    subPlan: Refer(Plan())

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


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.


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)

Tags:

Python