溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何解決Python相互導(dǎo)入的問題

發(fā)布時間:2022-01-06 12:48:31 來源:億速云 閱讀:114 作者:柒染 欄目:開發(fā)技術(shù)

本篇文章為大家展示了如何解決Python相互導(dǎo)入的問題,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

    問題描述

    兩個文件間相互導(dǎo)入時產(chǎn)生了一系列錯誤,比如 ImportError, NameError 等等。這次,我用簡單的代碼示例復(fù)現(xiàn)一下這些問題,并一步一步解決。

    問題復(fù)現(xiàn)

    這里,我創(chuàng)建兩個同目錄下的 Python 文件:mutualImportA 和 mutualImportB 并輸入代碼。

    # mutualImportA.py  
      
    from mutualImportB import b
      
    a = 1  
      
      
    def pA():  
        print(b)  
      
      
    pA()
    # mutualImportB.py  
      
    from mutualImportA import a  
      
    b = 1  
      
      
    def pB():  
        print(a)  
      
      
    pB()
    創(chuàng)建完畢后,任意運行 A 或 B 都會報錯:ImportError: cannot import name 'b' from partially initialized module 'mutualImportB' (most likely due to a circular import)當(dāng)然有些人習(xí)慣于用 import 的導(dǎo)入而非 from import 的導(dǎo)入方式,這時候的報錯就會變成:AttributeError: partially initialized module 'mutualImportB' has no attribute 'b' (most likely due to a circular import)

    好的,這兩個報錯還算友好。這種導(dǎo)入的方式都在程序出指明了導(dǎo)入的內(nèi)容,所以解釋器可以發(fā)現(xiàn)這里是循環(huán)導(dǎo)入(most likely due to a circular import)。但有時出現(xiàn)的 NameError 才真正讓人頭疼。

    我們將代碼改一下,保留 from import 語句,但將其 import 后面的變量名改為通配符 * 。這次的報錯:
    NameError: name 'b' is not defined

    這就很奇怪了。我們在使用 IDE 時, IDE 不會檢出相互導(dǎo)入時引發(fā)的循環(huán)導(dǎo)入問題。不過前兩種在報錯中即可看出,而這時,從報錯中很難發(fā)現(xiàn)為何 b 沒有聲明。這種專為復(fù)現(xiàn)而出現(xiàn)的小文件中問題可以捋清思路、找到問題,在較大的項目中就往往無從下手了。

    那么為什么會出現(xiàn)這樣的情況呢?我們想一下整個程序的運行流程。

    如何解決Python相互導(dǎo)入的問題

    問題復(fù)現(xiàn)完畢,下面探討如何解決問題。

    解決問題

    此前,我曾在許多平臺看到過文章,但其中絕大部分都是完全重復(fù)的(尤其在 CSDN 上),明顯互相“轉(zhuǎn)載”來“轉(zhuǎn)載”去??上?,轉(zhuǎn)載的文章并不能真正解決問題。在這篇原創(chuàng)的文章中,我將自己摸索的經(jīng)驗分享了出來。下面轉(zhuǎn)入正題。

    循環(huán)導(dǎo)入的根本原因是什么?為什么會循環(huán)導(dǎo)入?
    其實由循環(huán)導(dǎo)入,我們可以想到遞歸而引發(fā)的棧溢出。

    def a(b):
        return a(b)
    這,是一個明顯錯誤的函數(shù)。一旦我們調(diào)用了函數(shù),函數(shù)內(nèi)部就會不加判斷地再次調(diào)用此函數(shù)。
    而當(dāng)我們加入了判斷時:
    def a(b):
    	if b == 1:
    		return 1
    	else:
    		return a(b - 1)
    這樣的話,該函數(shù)就轉(zhuǎn)變?yōu)橐粋€健康的函數(shù)了。

    將同樣的思路運用到相互導(dǎo)入的方式上。我們必須在整個文件初就要導(dǎo)入某個模塊嗎?一般來說不是的。我們應(yīng)當(dāng)將導(dǎo)入放在它真正被需要的函數(shù)里。比如,問題復(fù)現(xiàn)中的 a、b 改一下:

    # mutualImportA.py  
      
    a = 1  
      
      
    def pA():  
    	from mutualImportB import b
        print(b)  
      
      
    pA()
    # mutualImportB.py  
      
      
    b = 1  
      
      
    def pB():  
    	from mutualImportA import a  
        print(a)  
      
      
    pB()
    這樣的話,就沒有上面的循環(huán)導(dǎo)入的問題了。這次再劃分下流程:

    如何解決Python相互導(dǎo)入的問題

    OK,那么問題到此為止就解決完畢了。

    當(dāng)然,據(jù)此問題也衍生出了一些代碼的規(guī)范問題:
    開發(fā)中,若文件較小,還是最好不要將需要相互使用的兩個函數(shù)或類分到兩個文件中。這樣,可以避免不少的問題。

    上述內(nèi)容就是如何解決Python相互導(dǎo)入的問題,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

    向AI問一下細節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI