self理解 & 子類調用父類函數的方法

1、self的含義

類是抽象的模板,實例是根據類創建出的一個個具體對象。

下面代碼中,andy_1.run() 會被python解釋器轉化爲 Dog.run(andy_1),可以看到對象 andy_1 被傳給了參數 self,用於表明是Dog類的哪個對象在調用run方法。

這種指明是Dog類的哪個對象在調用run方法,被稱爲將run方法綁定到andy_1 對象。

這就是爲什麼類中定義的函數(包括__init__),都要用self作爲第一個參數,就是用來接受具體的對象。特別說明的是,不一定非要用self做參數名,用a b c等任意變量名均可,self只是約定俗成的習慣。

即便是被系統自動調用的函數,如__init__,系統也會將要初始化的對象傳遞給__init__方法的 self 參數。(__init__並不是c++中的構造方法,d=Dog(‘andy’) 實際會等價於 d=object.__new__(Dog),Dog.__init__(d, ‘andy’) 兩條語句,即調用init前,對象已經被創建完成。

class Dog(object):
    def __init__(self, name):
        self.name = name

    def run(self):
         print self.name, 'is running'

andy_1 = Dog('andy_1')
andy_1.run()
andy_2 = Dog('andy_2')
andy_2.run()

2、子類調用父類的函數

子類調用父類有兩種方式:通過父類名 或 通過super函數。
我們用最常見的是調用父類的 __init__()方法說明。
(1)使用父類名
實際上使用了python解釋器的方式調用類的函數,即將父類的 init 函數綁定到b1上。注意 A.__init__(self) 這行代碼中,self參數實際已經被賦值爲 b1 對象。

class A(object):
    def __init__(self):
        print 'in A init'

class B(A):
    def __init__(self):
        A.__init__(self)

b1 = B()

這種方式有一個缺點,當子類的父類變化爲其他類時,所有顯示使用父類名的地方都要被修改爲新的父類名。因此,推薦使用super 函數的方式調用父類函數。

(2)使用super函數:super(type, [type-or-object])
super函數返回的不一定是父類,實際是MRO表中下一個類。:
super做的是下面這件事

def super(cls, inst):
    mro_list = inst.__class__.mro()
    return mro_list[mro_list.index(cls) + 1]

兩個參數 cls 和 inst 分別做了兩件事:
1. inst 負責生成 MRO 的 list
2. 通過 cls 定位當前 MRO 中的 index,並返回 mro[index + 1]

舉例:

class A(object):
    def __init__(self):
        print 'in A init'

class B(A):
    def __init__(self):
        super(B, self).__init__()
b = B()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章