在Python類(lèi)的方法(method)中,要調(diào)用父類(lèi)的某個(gè)方法,在Python 2.2以前,通常的寫(xiě)法如代碼段1:
代碼段1:
class A: def __init__(self): print "enter A" print "leave A" class B(A): def __init__(self): print "enter B" A.__init__(self) print "leave B" >>> b = B() enter B enter A leave A leave B
即,使用非綁定的類(lèi)方法(用類(lèi)名來(lái)引用的方法),并在參數(shù)列表中,引入待綁定的對(duì)象(self),從而達(dá)到調(diào)用父類(lèi)的目的。
這樣做的缺點(diǎn)是,當(dāng)一個(gè)子類(lèi)的父類(lèi)發(fā)生變化時(shí)(如類(lèi)B的父類(lèi)由A變?yōu)镃時(shí)),必須遍歷整個(gè)類(lèi)定義,把所有的通過(guò)非綁定的方法的類(lèi)名全部替換過(guò)來(lái),例如代碼段2,
代碼段2:
class B(C): # A --> C def __init__(self): print "enter B" C.__init__(self) # A --> C print "leave B"
如果代碼簡(jiǎn)單,這樣的改動(dòng)或許還可以接受。但如果代碼量龐大,這樣的修改可能是災(zāi)難性的。很容易導(dǎo)致修改錯(cuò)誤的出現(xiàn)。
因此,自Python 2.2開(kāi)始,Python添加了一個(gè)關(guān)鍵字super,來(lái)解決這個(gè)問(wèn)題。下面是Python 2.3的官方文檔說(shuō)明:
super(type[, object-or-type]) Return the superclass of type. If the second argument is omitted the super object returned is unbound. If the second argument is an object, isinstance(obj, type) must be true. If the second argument is a type, issubclass(type2, type) must be true. super() only works for new-style classes. A typical use for calling a cooperative superclass method is: class C(B): def meth(self, arg): super(C, self).meth(arg) New in version 2.2.
從說(shuō)明來(lái)看,可以把類(lèi)B改寫(xiě)如代碼段3:
代碼段3:
class A(object): # A must be new-style class def __init__(self): print "enter A" print "leave A" class B(C): # A --> C def __init__(self): print "enter B" super(B, self).__init__() print "leave B"
嘗試執(zhí)行上面同樣的代碼,結(jié)果一致,但修改的代碼只有一處,把代碼的維護(hù)量降到最低,是一個(gè)不錯(cuò)的用法。因此在我們的開(kāi)發(fā)過(guò)程中,super關(guān)鍵字被大量使用,而且一直表現(xiàn)良好。
1. super并不是一個(gè)函數(shù),是一個(gè)類(lèi)名,形如super(B, self)事實(shí)上調(diào)用了super類(lèi)的初始化函數(shù),產(chǎn)生了一個(gè)super對(duì)象;
2. super類(lèi)的初始化函數(shù)并沒(méi)有做什么特殊的操作,只是簡(jiǎn)單記錄了類(lèi)類(lèi)型和具體實(shí)例;
3. super(B, self).func的調(diào)用并不是用于調(diào)用當(dāng)前類(lèi)的父類(lèi)的func函數(shù);
4. Python的多繼承類(lèi)是通過(guò)mro的方式來(lái)保證各個(gè)父類(lèi)的函數(shù)被逐一調(diào)用,而且保證每個(gè)父類(lèi)函數(shù)只調(diào)用一次(如果每個(gè)類(lèi)都使用super);
5. 混用super類(lèi)和非綁定的函數(shù)是一個(gè)危險(xiǎn)行為,這可能導(dǎo)致應(yīng)該調(diào)用的父類(lèi)函數(shù)沒(méi)有調(diào)用或者一個(gè)父類(lèi)函數(shù)被調(diào)用多次。
從super關(guān)鍵字的help我們也能看出來(lái)。
Help on class super in module __builtin__:
class super(object)
| super(type) -> unbound super object
| super(type, obj) -> bound super object; requires isinstance(obj, type)
| super(type, type2) -> bound super object; requires issubclass(type2, type)
| Typical use to call a cooperative superclass method:
| class C(B):
| def meth(self, arg):
| super(C, self).meth(arg)
|
| Methods defined here:
.......
從上面也能看出來(lái),super是一個(gè)類(lèi),而且是__builtin__模塊中的。
從上面的描述來(lái)看,super主要是用于調(diào)用父類(lèi)的方法。
那么,在2.2之前的方法也能調(diào)用。為啥非得用super呢?
這是因?yàn)閟uper能夠阻止對(duì)父類(lèi)方法的多次調(diào)用。
super,改變了父類(lèi)搜索順序, 返回的是一個(gè)特殊的父類(lèi)對(duì)象
看例子:
class A: pass class B(A): pass class C(A):pass class D(B, C): pass
這是4個(gè)類(lèi)的基本關(guān)系。
假如不使用super,讓D的對(duì)象調(diào)用他們共有的一個(gè)方法,會(huì)2次調(diào)用A中這個(gè)方法。
希望本文所述對(duì)大家的Python程序設(shè)計(jì)有所幫助。
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com