Python 多繼承中的super 與MRO

2021-08-16 11:02:56 字數 3149 閱讀 5653

繼承:單繼承:

#父類

class animal(object):

"""docstring for animal"""

def __init__(self, name):

self.name = name;

def run(self):

print(" is running".format(self.name))

def eat(self):

print(" is eatting".format(self.name))

#子類class dog(animal):

def __init__(self, name):

self.name = name;

# 子類呼叫父類中已有的方法

def animal_run(self):

print("\ncalling father's method:")

animal.run(self)

dog = dog("chichi")

dog.run()

dog.eat()

dog.animal_run()

執行結果:

[chichi] is running

[chichi] is eatting

calling father's method:

[chichi] is running

在單繼承的情況下,我們可以直接在子類中通過父類名.method()來呼叫父類的方法。

多繼承:

class a(object):

def __init__(self):

self.n = 'a'

print("i'm a, i am called from c")

def func(self):

print("self is in a.func".format(self))

self.n += 'a'

class b(a):

def __init__(self):

self.n = 'b'

print("i'm b, i am called from d")

def func(self):

print("self is in b.func".format(self))

super().func()

self.n += 'b'

class c(a):

def __init__(self):

self.n = 'c'

print("i'm c, i am called from b")

def func(self):

print("self is in c.func".format(self))

super().func()

self.n += 'c'

class d(b, c):

def __init__(self):

self.n = 'd'

super(d, self).func()

def func(self):

print("self is in d.func".format(self))

# super().func()

print(d.mro())

a.__init__(self)

print("calling by super():")

super(b,self).__init__()

self.n += 'd'

d = d()

d.func()

執行結果:

self is <__main__.d object at> in b.func

self is <__main__.d object at> in c.func

self is <__main__.d object at> in a.func

self is <__main__.d object at> in d.func

[, , , , ]

i'm a, i am called from c

calling by super():

i'm c, i am called from b

在多繼承中,我們也可以直接指明父類名並呼叫其中的方法,但這樣做需要我們直接寫出父類名,這在很多時候是很麻煩的事情。當該子類的父類名稱變化時,我們就需要修改很多地方的呼叫,所以在python2中引入了super()方法。

1. 我們在寫d的__init__()方法時,可以直接用如下**來呼叫其父類的初始化方法,然後在父類的基礎上繼續新增子類的個性化方法。

super(d,self).__init__()
2. 甚至我們可以完全不寫d的__init__(),當建立d的物件時,自動從父類繼承__init()__方法。

但在多繼承中,

1. 乙個子類有兩個父類時,應該呼叫哪個父類的方法呢?

2. 該例中,super是怎麼決定呼叫b還是c的init的呢?

3. 或者當直接的父類也沒有init函式,那是不是就直接繼續去找父類的父類呢?

python多繼承問題實質上是鑽石繼承問題(diamond inheritance):

對於該問題的解決方法是,規定乙個mro(method resolution order),所以在上例中,mro是d->b->c->a->object, 按該順序呼叫我們就能找到上面問題的答案。

1. 多繼承中,子類會按照mro呼叫排在自己下乙個的類中的方法。

2. 按照mro中的順序呼叫。

3. 當最初被呼叫的類沒有該方法時,python會按照mro的順序乙個乙個向前查詢,直到找到該方法。但需要注意的是,當d,b都沒有定義init時,呼叫的是c 而不是a 的init。

那麼mro順序是怎麼確定的呢?

一句話總結:父類總是出現在子類後,若有多個父類,其相對順序保持不變,在定義子類調參時,父類的順序就已經決定了mro順序。

這裡有一篇對mro順序的**,給出了很多有趣的例子。

Python中的多繼承

python和c 一樣,支援多繼承。概念雖然容易,但是困難的工作是如果子類呼叫乙個自身沒有定義的屬性,它是按照何種順序去到父類尋找呢,尤其是眾多父類中有多個都包含該同名屬性。class p1 object deffoo self print p1 foo class p2 object deffoo...

python中的多繼承

一 介紹 python同樣有限的支援多繼承形式。多繼承的類定義形如下例 class derivedclassname base1,base2,base3 需要注意圓括號中父類的順序,若是父類中有相同的方法名,而在子類使用時未指定,python從左至右搜尋 即方法在子類中未找到時,從左到右查詢父類中是...

Python中的多繼承

coding utf8 1.多繼承 子類有多個父類 class human def init self,self.defp self print 這是human的方法 class person def init self,name self.name name defp self print 這是p...