2009-06-25 112 views
6

我有兩個相互引用的類,但顯然編譯器會抱怨。有沒有辦法解決?彼此相關的python類

編輯

其實我的代碼比漢克蓋伊使用略有不同。所以Python可以肯定地處理某些類型的循環引用,但是在以下情況下拋出一個錯誤。下面是我得到的,我得到一個'名稱Y未定義錯誤'

class X(models.Model): 

     creator = Registry() 
     creator.register(Y) 

class Y(models.Model): 
    a = models.ForeignKey(X) 
    b = models.CharField(max_length=200) 

希望這有助於澄清。有什麼建議麼。

+4

什麼是「明顯」?它在哪裏投訴?顯示代碼?循環引用對Python來說不​​成問題,問題在於別處。 – 2009-06-25 20:43:24

+0

代碼是什麼樣的? – 2009-06-25 20:43:32

+0

哇... * rolleyes * – Robbie 2009-06-25 20:55:43

回答

15

在python中,類加載時運行類中的代碼。

現在,這到底意味着什麼? ;-)

考慮下面的代碼:

class x: 
    print "hello" 
    def __init__(self): print "hello again" 

當加載包含代碼的模塊,Python會打印hello。無論何時創建x,python都會打印hello again

您可以認爲def __init__(self): ...__init__ = lambda self: ...等效,但沒有應用python lambda限制。也就是說,def是一個賦值,它可以解釋爲什麼運行代碼以外的方法而不是內部方法。

當你的代碼說

class X(models.Model): 
    creator = Registry() 
    creator.register(Y) 

您參考Y加載模塊時,Y有一個值之前。你能想到的class X作爲賦值(但我不記得創建匿名類離手的語法;也許它是type調用?)

你可能想要做的是這樣的:

class X(models.Model): 
    pass 
class Y(models.Model): 
    foo = something_that_uses_(X) 
X.bar = something_which_uses(Y) 

也就是說,在創建Y之後,創建參考YX的類屬性。或者反之亦然:先創建Y,然後創建X,然後根據X確定Y的屬性,如果更簡單。

希望這有助於:)

2

更新:他在我的答案後改變了問題。鑑於新的問題,目前接受的解決方案更好。

你說什麼是問題?

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() 

這個編譯和運行就好了。

2

只要你在一個方法內工作,你可以訪問類對象。

因此,如果creator.register(Y)移動到__init__以內,上述示例沒有問題。但是,您不能對方法外的類進行循環引用。

2

該錯誤是類X的(可執行)的定義期間嘗試的creator.register(Y)的執行,並且在該階段,沒有定義Y類。理解這一點:classdef是執行的語句(通常在導入時);他們不是「聲明」。

建議:告訴我們你想達到什麼 - 也許是一個新問題。

-2

這個問題很可能不是Python。我認爲這是一個SQL問題。這些類通過抽象層轉換爲SQL查詢來創建表。 您試圖從另一個表中引用當時還不存在的一個表。

在SQL你會首先創建表,而不引用解決這個問題,之後對其進行修改,使這些引用,

但是我不知道我的回答,所以把它有很多調料的,我如果Django的數據庫抽象層不能很好地處理交叉引用,實際上會非常驚訝。