1. 程式人生 > >解讀python中SocketServer原始碼

解讀python中SocketServer原始碼

再看繼承

  真正的大餐來之前,還是來點兒開胃菜!回顧一下關於類的繼承的知識:

  

  我們先看上面的程式碼,這是一個簡單的類繼承,我們可以看到父類Base和子類Son,它們中各有一個Testfunc方法,當我們例項化子類的物件sonobj時,可以看到初始化方法中黃色框框呼叫了Testfunc,那麼這個時候執行的是哪個類裡面的程式碼呢?我會告訴你執行的是子類裡面的方法,不信就自己試試吧,程式碼在下面~

  為什麼呢?其實這裡是繞了一個圈,所以把很多人繞暈了,包括我!後來想想其實很容易,我們看最右邊的圖:

  如果這樣看,我們是不是就明白了?其實這兩段程式碼表示的是一個意思,儘管Son繼承了Base類,父子類中都有同樣的方法,但是由於我們例項化了子類的物件,所以這個在初始化方法裡的self.Testfunc,self指的是子類的物件,當然也就先呼叫子類中的方法啦。所以儘管在第一個例子中,初始化方法在父類執行,但是還是改變不了它是子類物件的本質,當我們使用self去呼叫Testfunc方法時,始終是先呼叫子類的方法。我們可以這樣理解,儘管兒子繼承了父親的財產,但是花錢的時候,還是要先花自己的~~~

 1 #_*_coding:utf-8_*_
 2 __author__ = 'Eva_J'  3 class Base(object):  4 def __init__(self,name):  5 self.name = name  6  self.Testfunc()  7  8 def Testfunc(self):  9 print 'do Base Testfunc' 10 11 class Son(Base): 12 def Testfunc(self): 13 print 'do Son Testfunc' 14 15 sonobj = Son('sonobj')
inherit Code

       看完剛剛的程式碼,我們就知道了物件和self的真實意義,現在再來回憶一下關於繼承的順序問題:                        

       

   看上面的程式碼,我們猜測一下,執行之後,控制檯會列印什麼呢?先揭曉答案,會列印Base2方法中的內容,原因很簡單:儘管這三個類中都有同樣的Testfunc方法,但是,由於計算機在找方法的時候,遵循的順序是:Base2,Son,Base,所以它會先找到Base2類,而這個類中剛好有它要找的方法,它也就歡歡喜喜的拿去執行啦!

 1 #_*_coding:utf-8_*_
 2 __author__ = 'Eva_J'
 3 class Base(object):
 4     def Testfunc(self):
 5         print 'do Base Testfunc'
 6 
 7 class Son(Base):
 8     def __init__(self,name):
 9         self.name = name
10         self.Testfunc()
11 
12     def Testfunc(self):
13         print 'do Son Testfunc'
14 
15 class Base2(object):
16     def Testfunc(self):
17         print 'do Base2 Testfunc'
18 
19 class GrandSon(Base2,Son):
20     pass
21 
22 #sonobj = Son('sonobj')
23 sonobj = GrandSon('sonobj')
inherit2 Code

畫個簡易類圖

  剛剛我們只是寫了一個小程式,來說明類之間的繼承和物件呼叫方法之間的聯絡,但是如果我們想要hold住一個繼承關係複雜的原始碼邏輯,就需要類圖來幫忙!如果你覺得我要教你畫類圖那就大錯特錯了。。。懶人症重症患者是懶得畫那種東西的。。。嘻,先看圖!

對照類圖看原始碼

  根據上面的圖,我們就拿到了threadingTCPServer的相關類,並且搞清楚了它們之間的繼承關係和方法,接下來我們對照這張簡易類圖來看看程式碼執行的過程:

  初始化相關過程:

 

   執行serve_forever的相關程式碼:

  就是這樣,我們一路按照呼叫軌跡去尋找,每次看到一個呼叫都先對照上面的簡易類圖,看看有沒有重名方法,如果有,就要找到最近的方法並檢視裡面的內容,以此類推:按照這種方法,就會感覺所有程式碼都在一個檔案一樣,媽媽再也不用擔心我看不懂原始碼,哈!!!當然啦,這種方法比較山寨,自己心裡知道就好,不要告訴別人你其實是這樣看懂原始碼的~~~

再看繼承

  真正的大餐來之前,還是來點兒開胃菜!回顧一下關於類的繼承的知識:

  

  我們先看上面的程式碼,這是一個簡單的類繼承,我們可以看到父類Base和子類Son,它們中各有一個Testfunc方法,當我們例項化子類的物件sonobj時,可以看到初始化方法中黃色框框呼叫了Testfunc,那麼這個時候執行的是哪個類裡面的程式碼呢?我會告訴你執行的是子類裡面的方法,不信就自己試試吧,程式碼在下面~

  為什麼呢?其實這裡是繞了一個圈,所以把很多人繞暈了,包括我!後來想想其實很容易,我們看最右邊的圖:

  如果這樣看,我們是不是就明白了?其實這兩段程式碼表示的是一個意思,儘管Son繼承了Base類,父子類中都有同樣的方法,但是由於我們例項化了子類的物件,所以這個在初始化方法裡的self.Testfunc,self指的是子類的物件,當然也就先呼叫子類中的方法啦。所以儘管在第一個例子中,初始化方法在父類執行,但是還是改變不了它是子類物件的本質,當我們使用self去呼叫Testfunc方法時,始終是先呼叫子類的方法。我們可以這樣理解,儘管兒子繼承了父親的財產,但是花錢的時候,還是要先花自己的~~~

 1 #_*_coding:utf-8_*_
 2 __author__ = 'Eva_J'  3 class Base(object):  4 def __init__(self,name):  5 self.name = name  6  self.Testfunc()  7  8 def Testfunc(self):  9 print 'do Base Testfunc' 10 11 class Son(Base): 12 def Testfunc(self): 13 print 'do Son Testfunc' 14 15 sonobj = Son('sonobj')
inherit Code

       看完剛剛的程式碼,我們就知道了物件和self的真實意義,現在再來回憶一下關於繼承的順序問題:                        

       

   看上面的程式碼,我們猜測一下,執行之後,控制檯會列印什麼呢?先揭曉答案,會列印Base2方法中的內容,原因很簡單:儘管這三個類中都有同樣的Testfunc方法,但是,由於計算機在找方法的時候,遵循的順序是:Base2,Son,Base,所以它會先找到Base2類,而這個類中剛好有它要找的方法,它也就歡歡喜喜的拿去執行啦!

 1 #_*_coding:utf-8_*_
 2 __author__ = 'Eva_J'
 3 class Base(object):
 4     def Testfunc(self):
 5         print 'do Base Testfunc'
 6 
 7 class Son(Base):
 8     def __init__(self,name):
 9         self.name = name
10         self.Testfunc()
11 
12     def Testfunc(self):
13         print 'do Son Testfunc'
14 
15 class Base2(object):
16     def Testfunc(self):
17         print 'do Base2 Testfunc'
18 
19 class GrandSon(Base2,Son):
20     pass
21 
22 #sonobj = Son('sonobj')
23 sonobj = GrandSon('sonobj')
inherit2 Code

畫個簡易類圖

  剛剛我們只是寫了一個小程式,來說明類之間的繼承和物件呼叫方法之間的聯絡,但是如果我們想要hold住一個繼承關係複雜的原始碼邏輯,就需要類圖來幫忙!如果你覺得我要教你畫類圖那就大錯特錯了。。。懶人症重症患者是懶得畫那種東西的。。。嘻,先看圖!

對照類圖看原始碼

  根據上面的圖,我們就拿到了threadingTCPServer的相關類,並且搞清楚了它們之間的繼承關係和方法,接下來我們對照這張簡易類圖來看看程式碼執行的過程:

  初始化相關過程:

 

   執行serve_forever的相關程式碼:

  就是這樣,我們一路按照呼叫軌跡去尋找,每次看到一個呼叫都先對照上面的簡易類圖,看看有沒有重名方法,如果有,就要找到最近的方法並檢視裡面的內容,以此類推:按照這種方法,就會感覺所有程式碼都在一個檔案一樣,媽媽再也不用擔心我看不懂原始碼,哈!!!當然啦,這種方法比較山寨,自己心裡知道就好,不要告訴別人你其實是這樣看懂原始碼的~~~