Python面試題1:類變數在繼承中的深入理解

pythontab發表於2015-11-08

以下的程式碼的輸出將是什麼? 說出你的答案並解釋。

class Parent(object):
    x = 1
class Child1(Parent):
    pass
class Child2(Parent):
    pass
print Parent.x, Child1.x, Child2.x
Child1.x = 2
print Parent.x, Child1.x, Child2.x
Parent.x = 3
print Parent.x, Child1.x, Child2.x

答案

以上程式碼的輸出是:

1 1 1

1 2 1

3 2 3

使你困惑或是驚奇的是關於最後一行的輸出是 3 2 3 而不是 3 2 1。為什麼改變了 Parent.x 的值還會改變 Child2.x 的值,但是同時 Child1.x 值卻沒有改變?

這個答案的關鍵是,在 Python 中,類變數在內部是作為字典處理的。如果一個變數的名字沒有在當前類的字典中發現,將搜尋祖先類(比如父類)直到被引用的變數名被找到(如果這個被引用的變數名既沒有在自己所在的類又沒有在祖先類中找到,會引發一個 AttributeError 異常 )

因此,在父類中設定 x = 1 會使得類變數 X 在引用該類和其任何子類中的值為 1。這就是因為第一個 print 語句的輸出是 1 1 1。

隨後,如果任何它的子類重寫了該值(例如,我們執行語句 Child1.x = 2),然後,該值僅僅在子類中被改變。這就是為什麼第二個 print 語句的輸出是 1 2 1。

最後,如果該值在父類中被改變(例如,我們執行語句 Parent.x = 3),這個改變會影響到任何未重寫該值的子類當中的值(在這個示例中被影響的子類是 Child2)。這就是為什麼第三個 print 輸出是 3 2 3。


問題的關鍵點請看上述紅色文字!這個問題很基礎,但是相信有不少同學也會在這裡犯錯誤,所以平時基本功要做好。

相關文章