Does Python have class prototypes (or forward declarations)?

Solution 1:

Actually, all of the above are great observations about Python, but none of them will solve your problem.

Django needs to introspect stuff.

The right way to do what you want is the following:

class Car(models.Model):
    manufacturer = models.ForeignKey('Manufacturer')
    # ...

class Manufacturer(models.Model):
    # ...

Note the use of the class name as a string rather than the literal class reference. Django offers this alternative to deal with exactly the problem that Python doesn't provide forward declarations.

This question reminds me of the classic support question that you should always ask any customer with an issue: "What are you really trying to do?"

Solution 2:

In Python you don't create a prototype per se, but you do need to understand the difference between "class attributes" and instance-level attributes. In the example you've shown above, you are declaring a class attribute on class B, not an instance-level attribute.

This is what you are looking for:

class B():
    def __init__(self):
        self.c = C()

Solution 3:

This would solve your problem as presented (but I think you are really looking for an instance attribute as jholloway7 responded):

class A:
    pass

class B:
    pass

class C:
    pass

B.c = C()

Solution 4:

Python doesn't have prototypes or Ruby-style open classes. But if you really need them, you can write a metaclass that overloads new so that it does a lookup in the current namespace to see if the class already exists, and if it does returns the existing type object rather than creating a new one. I did something like this on a ORM I write a while back and it's worked very well.

Solution 5:

A decade after the question is asked, I have encountered the same problem. While people suggest that the referencing should be done inside the init method, there are times when you need to access the data as a "class attribute" before the class is actually instantiated. For that reason, I have come up with a simple solution using a descriptor.

class A():
    pass

class B():
    class D(object):
        def __init__(self):
            self.c = None
        def __get__(self, instance, owner):
            if not self.c:
                self.c = C()
            return self.c
    c = D()

class C():
    pass

>>> B.c
>>> <__main__.C object at 0x10cc385f8>