1. 程式人生 > 程式設計 >通過案例解析python鴨子型別相關原理

通過案例解析python鴨子型別相關原理

首先Python不支援多型,也不用支援多型,python是一種多型語言,崇尚鴨子型別。

在程式設計中,鴨子型別(英語:duck typing)是動態型別的一種風格。在這種風格中,一個物件有效的語義,不是由繼承自特定的類或實現特定的介面,而是由當前方法和屬性的集合決定。這個概念的名字來源於由James Whitcomb Riley提出的鴨子測試,

“鴨子測試”可以這樣表述:

“當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。”

在鴨子型別中,關注的不是物件的型別本身,而是它是如何使用的。例如,在不使用鴨子型別的語言中,我們可以編寫一個函式,它接受一個型別為鴨的物件,並呼叫它的走和叫方法。在使用鴨子型別的語言中,這樣的一個函式可以接受一個任意型別的物件,並呼叫它的走和叫方法。如果這些需要被呼叫的方法不存在,那麼將引發一個執行時錯誤。任何擁有這樣的正確的走和叫方法的物件都可被函式接受的這種行為引出了以上表述,這種決定型別的方式因此得名。

鴨子型別通常得益於不測試方法和函式中引數的型別,而是依賴文件、清晰的程式碼和測試來確保正確使用。從靜態型別語言轉向動態型別語言的使用者通常試圖新增一些靜態的(在執行之前的)型別檢查,從而影響了鴨子型別的益處和可伸縮性,並約束了語言的動態特性。

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

毫無疑問在python中物件也是一塊記憶體,記憶體中除了包含屬性、方法之外,還包含了物件得型別,我們通過引用來訪問物件,比如a=A(),首先python建立一個物件A,然後宣告一個變數a,再將變數a與物件A聯絡起來。變數a是沒有型別得,它的型別取決於其關聯的物件。a=A()時,a是一個A型別的引用,我們可以說a是A型別的,如果再將a賦值3,a=3,此時a就是一個整型的引用,但python並不是弱型別語言,在python中'2'+3會報錯,而在php中'2'+3會得到5。可以這麼理解,在python中變數類似與c中的指標,和c不同的是python中的變數可以指向任何型別,雖然這麼說不太準確,但是理解起來容易點。

因此,在python執行過程中,引數被傳遞過來之前並不知道引數的型別,雖然python中的方法也是後期繫結,但是和java中多型的後期繫結卻是不同的,java中的後期繫結至少知道物件的型別,而python中就不知道引數的型別。

還引用上次的例子:

class A:  
  def prt(self):  
    print "A"  
  
class B(A):  
  def prt(self):  
    print "B"  
      
class C(A):  
  def prt(self):  
    print "C"  
      
class D(A):  
  pass  
  
class E:  
  def prt(self):  
    print "E"  
  
class F:  
  pass  
  
def test(arg):  
  arg.prt()  
  
a = A()  
b = B()  
c = C()  
d = D()  
e = E()  
f = F()  
  
test(a)  
test(b)  
test(c)  
test(d)  
test(e)  
test(f)  

輸出結果:

A 
B 
C 
A 
E 
Traceback (most recent call last): 
 File "/Users/shikefu678/Documents/Aptana Studio 3 Workspace/demo/demo.py",line 33,in <module> 
  test(a),test(b),test(c),test(d),test(e),test(f) 
 File "/Users/shikefu678/Documents/Aptana Studio 3 Workspace/demo/demo.py",line 24,in test 
  arg.prt() 
AttributeError: F instance has no attribute 'prt' 

a,b,c,d都是A型別的變數,所以可以得到預期的效果(從java角度的預期),e並不是A型別的變數但是根據鴨子型別,走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子,e有prt方法,所以在test方法中e就是一個A型別的變數,f沒有prt方法,所以f不是A型別的變數。

以上是從java的角度分析的,其實上邊都是一派胡言,只是為了說明python中的執行方法。沒有誰規定test方法是接收的引數是什麼型別的。test方法只規定,接收一個引數,呼叫這個引數的prt方法。在執行的時候如果這個引數有prt方法,python就執行,如果沒有,python就報錯,因為abcde都有prt方法,而f沒有,所以得到了上邊得結果,這就是python的執行方式。

從學python有3個月了,雖然以前沒有怎麼好好學習過java,但是java方面的書看了不少很多思維方式都轉變不過來,總是想用java的思維方式來思考python的問題,實際上那樣只會南轅北轍,python中有太多的東西和java不一樣,從裡到外的不一樣。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。