2016-01-30 20 views
1

調用超級當我試圖理解下面的代碼。瞭解自己是什麼樣的孩子

class Base(object): 
    def __init__(self): 
     print(self.__class__.__name__) 
    def handle(self): 
     print("Beginning handle Base") 
     self.template() 
    def template(self): 
     print("template of Base") 

class Child(Base): 
    def __init__(self): 
     super(Child, self).__init__() 
    def handle(self): 
     print("Beginning handle Child") 
     super(Child, self).handle() 
    def template(self): 
     print("template of Child") 

parent = Base() 
child = Child() 

在這裏我希望下面的打印

'Base' 
'Child' 

所以這是好的,只是當我把這:

parent.handle() 
child.handle() 

我希望:

"Beginning handle Base" 
"template of Base" 
"Beginning handle Child" 
"Beginning handle Base" 
"template of Base" 

但是我得到

"Beginning handle Base" 
"template of Base" 
"Beginning handle Child" 
"Beginning handle Base" 
"template of Child" 

這究竟是爲什麼?在base的句柄函數中不是self.template()引用base的模板函數? super(Child, self).handle()究竟在做什麼?對我來說,似乎它調用了手柄的它的父,但設置自我本身......

+0

'Child'''''中的ChildB'是什麼? – ShadowRanger

+0

這應該是'孩子'......已更新問題 – barrigaj

+0

當調用'child.handle()'時,'self'始終是'child'。它被傳遞給'Base.handle',但它仍然是'child',所以當'Base.handle'調用'self.template()'時,它會調用'Child.template'。 –

回答

2

當沒有明確使用super時,會發生正常的動態查找,並且始終從真實類開始。 self.template()調用Base調用template功能正常的動態調度,並獲得Childtemplate,不Base S;假設如果Child覆蓋template,它的行爲比一個Base提供的更好。如果它不覆蓋,它會得到Base的版本。

認爲super折騰鏈只爲直接撥打電話super結果;否則,不涉及,並且發生正常查找(Base調用template就像其他人調用template一樣,根本沒什麼不同)。 selfBase通話而通過沒有什麼不同。

如果由於某種原因Base想阻礙動態查找(所以孩子們不能沒有去很多麻煩改變方法)它可以做兩種:

def handle(self): 
    print("Beginning handle Base") 
    Base.template(self) 

明確指定類或改變template__template觸發class私人訪問(無縫名稱修改),例如

def handle(self): 
    print("Beginning handle Base") 
    self.__template() 
def __template(self): 
    print("template of Base") 

即使Child做出了自己的__template,那__template是專用於Child,如果Base方法使用它不會被調用(但隨後的Child之外沒有一個既可以把它叫做無故障)。

4

Python 2 Documentation

super(type[, object-or-type])
返回一個代理對象,委託方法調用到父母或 兄弟班類型。這是用於訪問繼承方法 已在一類被覆蓋有用。搜索順序與getattr()使用的 相同,只是跳過類型本身。

你的情況 超(兒童,個體經營).handle

所以()下一個這樣做的:

調用的Child父(這是Base)的handle方法並傳遞Child實例作爲self該方法。

看看什麼在你的代碼片段會發生:

parent.handle() 
// Calling handle of parent, nothing special. 
// "Beginning handle Base" 
// "template of Base" 
child.handle() 
// Calling handle of child: "Beginning handle of Child" - logged 
// handle method of child calls handle method of parent: "Beginning handle Base" - logged 
// handle method of Base calls template method of self which is template method of Child as self passed to super as second parameter.: "template of Child" - logged 

所以這是對上面的代碼片斷正常行爲。