我在文件中有一系列Python类。有些课程会引用其他课程。
我的代码是这样的:
class A():
pass
class B():
c = C()
class C():
pass
尝试运行它,我得到NameError: name 'C' is not defined
。很公平,但有没有办法使它工作,或者我是否必须手动重新订购我的课程以适应?在C ++中,我可以创建一个类原型。 Python有一个等价的吗?
(我实际上正在使用Django模型,但我没有尝试使问题复杂化。)
答案 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>