假設同一資料夾下存在三個檔案:a.py, b.py 和run.py
a和b中定義a,b,c類,run.py執行呼叫
a中定義類a和c,b中定義類b,其中b是a的子類,c是b的子類,
因此b.py中需要import a,a.py中需要import b,造成迴圈引用
檔案內容分別如下(報錯版):
a.py
from b import b
classa:
name =
'a'def
print_self
(self)
:print
(self.name)
class
c(b)
: name =
'c'c = c(
)c.print_self(
)
b.py
from a import a
class
b(a)
: name =
'b'
run.py
from a import a, b, c
test_a = a(
)test_b = b(
)test_c = c(
)test_a.print_self(
)test_b.print_self(
)test_c.print_self(
)
執行run.py,執行結果:
結果說明:
run.py中執行from a import a, b, c時,由於a.py中的b是從b.py中import過來的,
會到b.py中執行**,遇到第一行from a import a,又回到a.py中執行from b import b,造成無限迴圈,編譯器報錯。
那怎麼處理呢?
注意到b繼承自a,c繼承自b,我們可以在需要使用到b時再import b,也即把a.py修改如下(正確執行版):
classa:
name =
'a'def
print_self
(self)
:print
(self.name)
from b import b
class
c(b)
: name =
'c'c = c(
)c.print_self(
)
執行結果:
1.第乙個"c"由a.py中c.print_self()輸出
2."a"由run.py中test_a.print_self()輸出
3."b"由run.py中test_b.print_self()輸出
4.第二個「c」由run.py中test_c.print_self()輸出
執行順序:
1.from a import a, b, c時,會把a.py中的**執行一遍
2.首先宣告class a
3.執行到第8行from b import b,到b.py中,執行from a import a,由於a已經被宣告,在這裡返回乙個a的引用,給b作父類(這是由於python編譯器把每個模組都視為單例,已經import的模組便不再import,只是在b.py中建立乙個a類的引用,供b類的宣告與初始化)。
4.回到a.py中宣告c,初始化c,執行c.print_self(),輸出第乙個"c"
5.a.py走完一遍,a,b,c均已宣告,from a import a, b, c返回a,b,c三個類的引用
6.run.py繼續往下執行,完成三個類的初始化與方法呼叫,依次輸出「a」,「b」,「c」
以上為能解釋現象的執行順序,僅供參考,是否正確,需要到python原始碼中找解答
---------------------------------update---------------------------------
上述方案能執行,但理解上是不正確的,因為直接執行a.py也報錯:
迴圈引用的處理
迴圈引用 兩個類互相引用,導致單純互相引用標頭檔案,編譯無法通過。解決方案 首先,要理解宣告和實現之間的差別。宣告只需要在使用類的前面新增class 而實現是包含具體成員函式和變數的類。如例1.class a class b 1.此時可在a的前面宣告class b,就可以使用b了。在b中只需要正常引...
Python迴圈引用的解決方案
1.延遲匯入 即將 from import yyy 放到函式或類的內部,從而使其作用域變成區域性的,但是這樣可能會對效能有些影響 2.將 from import yyy 轉換成 import yyy 的形式 3.以上兩種方式都是治標不治本的,只能說能夠用,但是並不符合規範,最好的辦法應該是從 布局入...
Python中迴圈的跳躍處理
python中的for迴圈是不允許改變迭代程序的,看下面的例子 wordlist 1 2 3 4 5 6 7 8 9 10 i 0for i in range len wordlist print wordlist i i 3然後輸出結果是 123 4567 8910這是因為在python的for迴...