确实Python的有类原型(或前向声明)?

问题描述 投票:32回答:6

我有一个文件中的一系列Python类的。有些类引用他人。

我的代码是这样的:

class A():
    pass

class B():
    c = C()

class C():
    pass

尝试运行,我得到NameError: name 'C' is not defined。不够公平,但有什么办法,使其工作,或者我需要手动重新整理我的课,以适应?在C ++中,我可以创建一个类的原型。 Python中是否有相同呢?

(实际上,我与Django模型玩,但我想不是使问题复杂化)。

python class oop prototype
6个回答
34
投票

在Python你不创建一个原型本身,而是你需要理解之间的“类属性”和实例级属性的差异。在您在上面示出的示例中,将声明类B,不是一个实例级属性上的类属性。

这是你在找什么:

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

50
投票

事实上,上述所有的都是关于Python伟大的意见,但没有人会解决你的问题。

Django的需要反思的东西。

做你想做什么是正确的方法如下:

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

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

注意,这里使用的类名作为一个字符串,而不是字面类引用。 Django还提供了这种替代对付正是Python没有提供前置声明的问题。

这个问题让我想起了经典的支持问题,你应该总是要求客户有一个问题:“什么是你真正想要做的”


8
投票

为呈现这将解决你的问题(但我认为你真正需要的实例属性为jholloway7回应):

class A:
    pass

class B:
    pass

class C:
    pass

B.c = C()

4
投票

Python没有原型或者Ruby式的公开课。但是,如果你真的需要它们,你可以写一个重载新,因此,它并看到在当前命名空间中查找,如果已经存在于类元类,如果它返回现有类型的对象,而不是创建一个新的。我做了这样的事情在一个ORM我写了一段时间后,它的工作非常出色。


0
投票

有关类VS实例属性所有正确的答案。但是,你有一个错误的原因是定义你的类的只是顺序。当然C类尚未定义(作为类级别代码被立即执行的上进口):

class A():
    pass

class C():
    pass

class B():
    c = C()

将工作。


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>
© www.soinside.com 2019 - 2024. All rights reserved.