1. 程式人生 > 其它 >002.python 多繼承呼叫指定父類同名方法的方法

002.python 多繼承呼叫指定父類同名方法的方法

技術標籤:Python全棧

如果子類和繼承了多個父類,並且這些父類中有多個方法的方法名一樣時,我該如何呼叫指定父類中的同名方法呢?不妨先舉一個小例子:

class A:
    def f_a(self):
        print('--------A--------')
class B:
    def f_a(self):
        print('-------B-------')
class C(A,B):
    def f_a(self):
        print('--------C--------')
c = C()
c.f_a()
>>> --
------C--------

如果我們想在C類中的f_a方法裡面使用父類A或者父類B的方法該如何操作呢?

方法有兩種:

方法一:把物件呼叫轉換為類呼叫:

class C(A,B):
    def f_a(self):
        A.f_a(self)
        B.f_a(self)
        print('--------C--------')
c = C()
c.f_a()

輸出結果為:

>>>--------A--------
>>>--------B--------
>>>--------C--------

這裡呼叫父類的f_a方法時括號裡面要寫self,表明這是一個類呼叫,但這種方法有一個缺點,比如說如果修改了父類的名稱,那麼在子類中會涉及多出修改,並且python是允許多繼承的語言,上述方法在多繼承時就要重複寫多次,顯得累贅,為了解決這些問題,python引進了super()機制,接下來想必大家都猜到了下一種呼叫父類的另一種方法了吧。

方法二:使用super()機制,引入super()方法:

class C(A,B):
    def f_a(self):
        super().f_a()
        print('--------C--------')
c = C()
c.
f_a()
>>>--------A--------
>>>--------C--------

這裡直接使用super()方法會呼叫A類的f_a方法,因為它會預設多繼承中從左到右的順序來呼叫,那麼有人就會問了,假如我想呼叫B類中的f_a方法是不是把A和B對調下呢,這種方法也行,不過這不算的上是一種較為巧妙的方法。
我們還可以使用super()方法,但要對其修改下:

class C(A,B):
    def f_a(self):
        super(C,self).f_a()
        super(A,self).f_a()
        print('--------C--------')
c = C()
c.f_a()
>>>--------A--------
>>>--------B--------
>>>--------C--------

看到沒,這樣寫:super(C,self).f_a()會呼叫最左邊的(即A類)的f_a方法,而super(A,self).f_a()會呼叫A類後面那個類的f_a()方法,若果繼承的不止兩個類,如果要呼叫某個類方法,只要知道前一個類名就可以呼叫。

下面給出一個例子,請讀者自行思考執行結果:

class Point(object):

    def __init__(self,x,y):

        self.x = x
        self.y = y

    def string(self):
        print("X:{0},Y:{1}".format(self.x,self.y))


# class Circle(Point):
#
#     def __init__(self,x,y,radius):
#         super().__init__(x,y)
#         self.radius = radius
#
#     def string(self):
#         print("該圖形初始化點為:({0},{1}),半徑為:{2}。".format(self.x,self.y,self.radius))


class Size:

    def __init__(self,width,heigth):
        self.width = width
        self.height = heigth

    def string(self):
        print("Width:{0},Height:{1}".format(self.width,self.height))


class Rectangle(Point,Size):

    def __init__(self,x,y,width,height):

        super(Rectangle,self).__init__(x,y)
        super(Point,self).__init__(width,height)
        #這裡值得注意的是,如果要跨過一個父類去另外一個父類呼叫同名方法時
        #應當在super()的引數中指定要繼承的類在繼承順序中的前一個類的名稱
        #如果沒有就把這個名稱寫成自己的類名


    def string(self):

        print("該圖形的初始化點為({0},{1}),長寬分別為Height:{2},Width:{3}".format(self.x,self.y,self.height,self.width))



if __name__ == '__main__':
    # c = Circle(0,0,100)
    # c.string()

    r = Rectangle(0,0,100,100)
    r.string()