python基礎:class類繼承


面向對象的編程帶來的主要好處之一是代碼的重用,實現各種重用的方法之一是通過繼承機制。繼承完全可以理解成類之間的父類和子類型關系。

繼承概念:繼承是類與類的一種關系,是一種子類與父類的關系,即爸爸與兒子,爸爸生個兒子,兒子繼承爸爸的屬性和方法。

如貓類,貓是動物;貓類繼承於動物類,動物類為父類也是所有動物的基類;貓類是動物類的子類,也是動物類的派生類。

Python有單繼承與多繼承。單繼承即子類繼承於一個類,多繼承即子類繼承於多個類,多繼承會比較少遇到,本章節主要講單繼承。

什么時候使用繼承:假如我需要定義幾個類,而類與類之間有一些公共的屬性和方法,這時我就可以把相同的屬性和方法作為基類的成員,而特殊的方法及屬性則在本類中定義。這樣子類只需要繼承基類(父類),子類就可以訪問到基類(父類)的屬性和方法了,它提高了代碼的可擴展性和重用行。

如:貓,狗 都屬於動物,它們行為相似性高,都會叫,會吃,會喝,會拉,會撒嬌。

一、Python類的繼承

如下定義一個動物類animal為基類,他的基本兩個實例屬性name和age\一個方法call

class Animal(object):  #  python3中所有類都可以繼承於object基類
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def call(self):
       print(self.name, '會叫')

######
# 現在我們需要定義一個Cat 貓類繼承於Animal,貓類比動物類多一個sex屬性。 
######
class Cat(Animal):
   def __init__(self,name,age,sex):
       super(Cat, self).__init__(name,age)  # 不要忘記從Animal類引入屬性
       self.sex=sex

if __name__ == '__main__':  # 單模塊被引用時下面代碼不會受影響,用於調試
   c = Cat('喵喵', 2, '')  #  Cat繼承了父類Animal的屬性
   c.call()  # 輸出 喵喵 會叫 ,Cat繼承了父類Animal的方法 

注意:一定要用 super(Cat, self).__init__(name,age) 去初始化父類,否則,繼承自 Animal的 Cat子類將沒有 name和age兩個屬性。
函數super(Cat, self)將返回當前類繼承的父類,即 Animal,然后調用__init__()方法,注意self參數已在super()中傳入,在__init__()中將隱式傳遞,不能再寫出self

二、Python 對子類方法的重構

上面例子中 Animal 的子類 Cat 繼承了父類的屬性和方法,但是我們貓類 Cat 有自己的叫聲 '喵喵' ,這時我們可以對父類的 Call() 方法進行重構。如下:

class Cat(Animal):
   def __init__(self, name, age, sex):
       super(Cat, self).__init__(name,age)
       self.sex = sex

   def call(self):
       print(self.name,'會“喵喵”叫')

if __name__ == '__main__':
   c = Cat('喵喵', 2, '')
   c.call()  # 輸出:喵喵 會“喵喵”叫

類方法的調用順序,當我們在子類中重構父類的方法后,Cat子類的實例先會在自己的類 Cat 中查找該方法,當找不到該方法時才會去父類 Animal 中查找對應的方法。

三、Python中子類與父類的關系

class Animal(object):
   pass

class Cat(Animal):
   pass

A= Animal()
C = Cat()

子類與父類的關系是 “is” 的關系,如上 Cat 繼承於 Animal 類,我們可以說:

“A”是 Animal 類的實例,但,“A”不是 Cat 類的實例。

“C”是 Animal 類的實例,“C”也是 Cat 類的實例。

判斷對象之間的關系,我們可以通過 isinstance (變量,類型) 來進行判斷:

print('"A" IS Animal?', isinstance(A, Animal)) print('"A" IS Cat?', isinstance(A, Cat)) print('"C" IS Animal?', isinstance(C, Animal)) print('"C" IS Cat?', isinstance(C, Cat))

輸出結果:

"A" IS Animal? True
"A" IS Cat? False
"C" IS Animal? True
"C" IS Cat? True

拓展:isinstance() 判斷變量類型

函數 isinstance() 不止可以用在我們自定義的類,也可以判斷一個變量的類型,如判斷數據類型是否為 int、str、list、dict 等。

print(isinstance(100, int)) print(isinstance('100', int)) print(isinstance(100, str)) print(isinstance('100', str))

輸出:

True
False
False
True

四、python 中多態

類具有繼承關系,並且子類類型可以向上轉型看做父類類型,如果我們從 Animal 派生出 Cat和 Dog,並都寫了一個 call() 方法,如下示例:

class Animal(object):  
   def __init__(self, name, age):
       self.name = name
       self.age = age
   def call(self):
       print(self.name, '會叫')

class Cat(Animal):
   def __init__(self, name, age, sex):
       super(Cat, self).__init__(name, age)
       self.sex = sex

   def call(self):
       print(self.name, '會“喵喵”叫')

class Dog(Animal):
   def __init__(self, name, age, sex):
       super(Dog, self).__init__(name, age)
       self.sex = sex
   def call(self):
       print(self.name, '會“汪汪”叫')

我們定義一個 do 函數,接收一個變量 ‘all’,如下:

def do(all):
   all.call()

A = Animal('小黑',4)
C = Cat('喵喵', 2, '')
D = Dog('旺財', 5, '')

for x in (A,C,D):
   do(x)
小黑 會叫
喵喵 會“喵喵”叫
旺財 會“汪汪”叫

小知識:多態

這種行為稱為多態。也就是說,方法調用將作用在 all 的實際類型上。C 是 Cat 類型,它實際上擁有自己的 call() 方法以及從 Animal 繼承的 call 方法,但調用 C .call() 總是先查找它自身的定義,如果沒有定義,則順着繼承鏈向上查找,直到在某個父類中找到為止。

傳遞給函數 do(all) 的參數 all 不一定是 Animal 或 Animal 的子類型。任何數據類型的實例都可以,只要它有一個 call() 的方法即可。其他類不繼承於 Animal,具備 call 方法也可以使用 do 函數。這就是動態語言,動態語言調用實例方法,不檢查類型,只要方法存在,參數正確,就可以調用。

五、Python類繼承 注意事項:

  • 在繼承中基類的構造方法(__init__()方法)不會被自動調用,它需要在其派生類的構造方法中親自專門調用。
  • 在調用基類的方法時,需要加上基類的類名前綴,且需要帶上self參數變量。而在類中調用普通函數時並不需要帶上self參數
  • Python 總是首先查找對應類的方法,如果它不能在派生類中找到對應的方法,它才開始到基類中逐個查找。(先在本類中查找調用的方法,找不到才去基類中找)
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM