2016-06-21 32 views
-2

在python中繼承類中調用構造函數的正確方法是什麼?構造函數在繼承類python中失敗

例如,

class A: 

    def __init__(self, x, y): 
     self.x = x 
     self.y = y 


class B(A): 

    def __init__(self, x, y, z): 
     self.z = z 
     # super().__init__(x, y) # <== works 
     super(x, y) # <== throws TypeError: must be type, not int 

a = A(2, 3) 
b = B(2, 3, 4) 

是否有可能調用構造不從基類調用__init __()方法?

+3

您是否仔細閱讀過'super()'文檔? –

回答

3

您使用super()錯誤的;您需要創建傳入當前類和self對象,然後引用繼承屬性:

super(B, self).__init__(x, y) 

super()然後使用type(self).__mro__搜索完全繼承樹中的方法解析順序(MRO),開始於下一個位置過去B,找到你想要的屬性。在這裏您正在尋找__init__,因此type(B).__mro__首先搜索B,然後從下一個條目開始,搜索__init__屬性,然後綁定到self。這樣您最後致電A.__init__(self, x, y)

注意super()可以用來找到在MRO任何繼承屬性,它不只是用於查找當前方法的基本實現。

super()只能在新式的類,這意味着在Python 2中使用您必須object開始你的繼承樹:

class A(object): 

object自動在Python的繼承樹的一部分3.

+0

因此,第一個參數是基類,第二個是對當前對象的引用,然後是實際的構造函數調用? – Sebi

+1

@Sebi:第一個參數是* current *類,而不是基類。這很重要,因爲當前類決定了完整的繼承層次結構以及方法解析順序。 'super()'充當代理,在MRO中搜索*任何屬性*,它不僅對當前方法有用。 –

+0

「TypeError:必須是類型,而不是classobj」的異常仍在拋出 – Sebi

2

這樣做:

super(B, self).__init__(x, y)