python super

mjiansun發表於2017-03-01

轉自:http://blog.csdn.net/imzoer/article/details/8743992

Python類的方法(method)中,要呼叫父類的某個方法,在Python 2.2以前,通常的寫法如程式碼段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


即,使用非繫結的類方法(用類名來引用的方法),並在引數列表中,引入待繫結的物件(self),從而達到呼叫父類的目的。

這樣做的缺點是,當一個子類的父類發生變化時(如類B的父類由A變為C時),必須遍歷整個類定義,把所有的通過非繫結的方法的類名全部替換過來,例如程式碼段2,

程式碼段2:

class B(C):    # A --> C
def __init__(self):
   print "enter B"
   C.__init__(self) # A --> C
   print "leave B"

如果程式碼簡單,這樣的改動或許還可以接受。但如果程式碼量龐大,這樣的修改可能是災難性的。很容易導致修改錯誤的出現。

因此,自Python 2.2開始,Python新增了一個關鍵字super,來解決這個問題。下面是Python 2.3的官方文件說明:

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.

從說明來看,可以把類B改寫如程式碼段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"

嘗試執行上面同樣的程式碼,結果一致,但修改的程式碼只有一處,把程式碼的維護量降到最低,是一個不錯的用法。因此在我們的開發過程中,super關鍵字被大量使用,而且一直表現良好。

-------------------------------

1. super並不是一個函式,是一個類名,形如super(B, self)事實上呼叫了super類的初始化函式,產生了一個super物件;
2. super類的初始化函式並沒有做什麼特殊的操作,只是簡單記錄了類型別和具體例項;
3. super(B, self).func的呼叫並不是用於呼叫當前類的父類的func函式;
4. Python的多繼承類是通過mro的方式來保證各個父類的函式被逐一呼叫,而且保證每個父類函式只呼叫一次(如果每個類都使用super);
5. 混用super類和非繫結的函式是一個危險行為,這可能導致應該呼叫的父類函式沒有呼叫或者一個父類函式被呼叫多次。

------------------------------

從super關鍵字的help我們也能看出來。

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:
.......

從上面也能看出來,super是一個類,而且是__builtin__模組中的。

---------------------------

從上面的描述來看,super主要是用於呼叫父類的方法。

那麼,在2.2之前的方法也能呼叫。為啥非得用super呢?

這是因為super能夠阻止對父類方法的多次呼叫。

super,改變了父類搜尋順序, 返回的是一個特殊的父類物件
看例子:
class A: pass class B(A): pass class C(A):pass class D(B, C): pass
這是4個類的基本關係。
假如不使用super,讓D的物件呼叫他們共有的一個方法,會2次呼叫A中這個方法。

相關文章