2017-02-16 83 views
2

我有兩個相互依賴的類(GraphQL類型定義)。我想將它們移到單獨的文件中。獨立文件中的相互依賴的類(循環導入)

只要他們在同一個文件中定義,沒有問題。

# all_schemas.py 

class AuthorSchema(graphene.ObjectType): 
    publications = graphene.List(lambda: PublicationSchema) 


class PublicationSchema(graphene.ObjectType): 
    author = graphene.Field(AuthorSchema) 

只要我把它們放到單獨的文件中,我就會遇到'循環導入'問題。

author_schema.py

from publication_schema import PublicationSchema 

class AuthorSchema(graphene.ObjectType): 
    publications = graphene.List(lambda: PublicationSchema) 

publication_schema.py

from author_schema import AuthorSchema 

class PublicationSchema(graphene.ObjectType): 
    author = graphene.Field(AuthorSchema) 

這裏是什麼,我相信,以顯示圓形進口問題上的錯誤:

我有哪些選擇爲了解決這個問題?

有人說循環進口是不好的做法,我不明白爲什麼會出現這種情況,但我想知道爲什麼。他們還建議重構代碼,但我想知道如何做到這一點,而不是結束一個包含所有相互依賴的類的大文件。

(請注意,我使用Python 2.7,在谷歌應用程序引擎)

+0

這是一個不好的做法,因爲在你的情況下,如果不知道'AutorSchema'是什麼('PublicationSchema'類屬性'author'依賴於它),你無法創建'PublicationSchema'類結構,但是你不能創建'首先是「AutorSchema」,因爲它的'publications'屬性依賴於'PublicationSchema'。這使得整個結構不合邏輯,Python解釋器無法知道你想實現什麼。 – zwer

+0

感謝@zwer,我不明白的是:只要一切都在同一個文件中定義,邏輯概念就可以正常工作。我試圖做的事情是重新組織代碼,而(工作)邏輯保持完全一樣...... – Hoff

+0

它被卡在導入上,因爲這是第一個命令,所以解釋器試圖加載你先給它的任何模塊。有了兩個相互關聯的依賴關係,當它嘗試加載依賴關係時,它將被拋回到它所來自的文件中,導致它不會解析第二個文件(以避免無限循環),從而無法加載依賴關係。當類在同一個文件中時,Python能夠解析循環依賴,因爲它首先創建指向類的指針,而不是先嚐試加載它們。 – zwer

回答

0

標準Python辦法來避免循環依賴,是爲了避免他們在導入時運行。而不是放置。例如,在PublicationSchema類中放入from author_schema import AuthorSchema,所以在從AuthorSchema導入此類時,它不會運行。但是,這是不穩定的,放置它們的確切點取決於代碼,並且可能隨代碼更改而改變。

標準的OOP方法是針對AuthorInterface,即發佈導入和作者實現。見非循環依賴原理依賴倒置原理

0

上述評論的地位,如果你真的,真的要做到這一點(和你不知道!),你可以隨時使用延遲進口在AuthorSchema

def get_publication_schema(): 
    from publication_schema import PublicationSchema 
    return PublicationSchema 

class AuthorSchema(graphene.ObjectType): 

    publications = graphene.List(get_publication_schema) 

的警告 - 你還贏了」因爲兩個文件都需要完全加載才能相互引用,所以不能執行autor_schema.py的「全局」空間中調用PublicationSchema的任何代碼。但在第三方使用情況下,這將起作用。

+0

hi @zwer,非常感謝您花時間幫助我。你說的是「如果你真的,真的必須這樣做(你不這樣做......)......」通過「做這個」,我假設你的意思是「把2個相互依賴的類放入單獨的文件」 - 好吧,我不不必這樣做,但這就是我想要構建代碼的方式 - 或者這是您選擇的不合理目標? – Hoff

+0

正如@blue_note上面所說的,具有互鎖依賴性違背了OOP原則。如上所述,你可以通過懶惰的導入來實現,但是你在技術上迫使語言使用你的結構思想,而不是被認爲是一種好的面向對象方法(一種清晰的初始者依賴樹)。由於所有事情最終都會變成程序執行,請嘗試遵循執行的過程,並且您會明白爲什麼Python會抱怨 - 這是模棱兩可的,將它拋出怪物。 – zwer

+0

我只是想說清楚一點,我說你不需要更多這樣的建議來重新考慮你的結構,因爲必須有一種方法來實現你的目標,而不會違揹你的編譯器/口譯員的精髓,也不會犧牲清晰的所有權/依賴結構。 – zwer