Python有类原型(或前向声明)吗?

时间:2009-02-07 22:21:50

标签: python class oop prototype

我在文件中有一系列Python类。有些课程会引用其他课程。

我的代码是这样的:

class A():
    pass

class B():
    c = C()

class C():
    pass

尝试运行它,我得到NameError: name 'C' is not defined。很公平,但有没有办法使它工作,或者我是否必须手动重新订购我的课程以适应?在C ++中,我可以创建一个类原型。 Python有一个等价的吗?

(我实际上正在使用Django模型,但我没有尝试使问题复杂化。)

6 个答案:

答案 0 :(得分:48)

实际上,上述所有内容都是关于Python的很好的观察,但没有一个能解决你的问题。

Django需要反省内容。

正确方式执行您想要的操作如下:

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

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

请注意使用类名作为字符串而不是文字类引用。 Django提供了这种替代方案来处理Python不提供前向声明的问题。

这个问题让我想起了一个经典的支持问题,你应该总是问任何有问题的客户:“你 尝试做什么?”

答案 1 :(得分:34)

在Python中,您本身并不创建原型,但您需要了解“类属性”和实例级属性之间的区别。在上面显示的示例中,您要声明B类的类属性,而不是实例级属性。

这就是你要找的东西:

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

答案 2 :(得分:8)

这将解决您提出的问题(但我认为您真的在寻找jholloway7响应的实例属性):

class A:
    pass

class B:
    pass

class C:
    pass

B.c = C()

答案 3 :(得分:4)

Python没有原型或Ruby风格的开放类。但是如果你确实需要它们,你可以编写一个重载 new 的元类,以便它在当前的命名空间中查找该类是否已经存在,如果它确实返回现有的类型对象而不是而不是创建一个新的。我在ORM上做了类似的事情,我写了一段时间后,它的效果非常好。

答案 4 :(得分:0)

关于类和实例属性的所有正确答案。但是,您遇到错误的原因只是定义类的顺序。当然还没有定义C类(因为在导入时会立即执行类级代码):

class A():
    pass

class C():
    pass

class B():
    c = C()

会工作。

答案 5 :(得分:0)

问了十年后,我遇到了同样的问题。尽管人们建议应在 init 方法内进行引用,但有时您需要在实际实例化类之前将数据作为“类属性”进行访问。因此,我提出了一个使用描述符的简单解决方案。

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>