相互引用的python类
我有两个类相互引用,但显然编译器会抱怨。这有什么办法吗 编辑 实际上,我的代码与Hank Gay使用的代码略有不同。因此python肯定可以处理某些类型的循环引用,但在以下情况下会抛出一个错误。下面是我得到的,我得到一个“名称Y未定义错误”相互引用的python类,python,django,oop,Python,Django,Oop,我有两个类相互引用,但显然编译器会抱怨。这有什么办法吗 编辑 实际上,我的代码与Hank Gay使用的代码略有不同。因此python肯定可以处理某些类型的循环引用,但在以下情况下会抛出一个错误。下面是我得到的,我得到一个“名称Y未定义错误” class X(models.Model): creator = Registry() creator.register(Y) class Y(models.Model): a = models.ForeignKe
class X(models.Model):
creator = Registry()
creator.register(Y)
class Y(models.Model):
a = models.ForeignKey(X)
b = models.CharField(max_length=200)
希望这有助于澄清。任何建议。更新:他在我回答后改变了问题。根据新问题,目前接受的解决方案更好 你是说问题出在哪里
class A(object):
def __init__(self):
super(A, self).__init__()
def b(self):
return B()
class B(object):
def __init__(self):
super(B, self).__init__()
def a(self):
return A()
这可以很好地编译和运行。只要在方法中工作,就可以访问类对象
因此,如果将
creator.register(Y)
移动到\uuuu init\uuu
内部,则上述示例没有问题。但是,不能在方法之外循环引用类。在python中,类中的代码在加载该类时运行
那到底是什么意思?;-)
考虑以下代码:
class x:
print "hello"
def __init__(self): print "hello again"
加载包含代码的模块时,python将打印hello
。无论何时创建x
,python都会再次打印hello
您可以将def\uu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuoself:…
视为与\uuuuuuuu。也就是说,def
是一个赋值,这可能解释了为什么在方法外部而不是在方法内部运行代码
当你的代码说
class X(models.Model):
creator = Registry()
creator.register(Y)
加载模块时,在Y
有值之前,请参考Y
。您可以将类X
视为一个赋值(但我记不起立即创建匿名类的语法;可能是调用类型
?)
您可能想做的是:
class X(models.Model):
pass
class Y(models.Model):
foo = something_that_uses_(X)
X.bar = something_which_uses(Y)
也就是说,在创建Y
之后,创建引用Y
的X
类属性。反之亦然:首先创建Y
,然后创建X
,然后创建依赖于X
的Y
属性(如果更容易的话)
希望这有帮助:)错误是在类X的(可执行)定义期间尝试执行creator.register(Y)
,而在该阶段,未定义类Y。理解这一点:class
和def
是执行的语句(通常在导入时执行);它们不是“宣言”
建议:告诉我们你想要实现什么——也许是一个新问题。问题很可能不是Python。我认为这是一个SQL问题。这些类通过抽象层转换为SQL查询来创建表。
您正试图从一个表引用另一个当时尚不存在的表
在SQL中,您可以通过首先创建不带引用的表来解决此问题,然后修改表以生成这些引用
但是我不确定我的答案,所以请仔细考虑一下,如果Django的数据库抽象层不能很好地处理交叉引用,我会非常惊讶,这看起来像是一个不言而喻的矛盾,我们试图想象两个独立但相互依赖的实体,仅仅从它们在物理世界中诞生的一个角度来看。但是,当涉及到软件领域时,我们经常会遇到这种问题,即所谓的“循环或相互引用”。这一点在面向对象设计中可能更为严重,在面向对象设计中,互操作软件元素通常以物理元素的方式定义并相互关联,但仍然是纯粹的逻辑存在
在许多编程语言中,这些问题都是通过在元素以函数或类的签名(无主体定义)的形式引用元素之前及时声明为引用元素来解决的。然而,对于基于脚本的语言(如Python),这种规避技巧似乎不再可用,也不再有用
在Python中,我们最好从软件工程的角度来处理“循环引用”,如下所示:
如果可能的话,最好重新设计非循环类;有几种方法(例如类de-或组合、回调函数、观察者或订阅者模式等)可以使元素之间的引用发生在同一个类中、移除或反转
如果将元素之间的某些循环链线性化可能会在质量或生产率等方面造成更严重的问题,我们可以采取另一种措施将其传统构建阶段分为两个阶段:创建和构造。
例如,朋友中的两个人在观察到对方的出生后就注定要有自己的出生,他们可以这样做:他们是第一次出生,然后在任何有意义和可观察的场合发生之前就有了他们的友谊。
请注意,如果我们在处理内部聚合对象时面临一些极端的复杂性或需要一些高度的完整性,那么应用工厂模式将获得回报
什么是“明显的”?它在哪里抱怨?显示代码?循环引用对Python来说不是问题,问题在别处。代码看起来像什么?这里是什么循环?Y根本不像我看到的那样参考X!在Y。。。a=型号。ForeignKey(X)请发布所有相关代码。此答案没有解释任何内容。它提供了一种“变通方法”,没有理解或解释真正的问题,这在Jonas和John Machin的回答中有解释。一些额外的信息:这很有效,是的。但它有一个代价:只有将所有类放在一个文件中,它才有效。这是非常不方便的:我不知道这可能是非常python的,但我知道它与良好的OOP实践相违背,即为每个(公共)类使用自己的文件