python學習筆記8 繼承和多型

2021-09-22 19:51:53 字數 3600 閱讀 7383

比如,我們已經編寫了乙個名為animal的class,有乙個run()方法可以直接列印:

class animal(object):

def run(self):

print('animal is running...')

當我們需要編寫dog和cat類時,就可以直接從animal類繼承:

**class dog(animal):

pass

class cat(animal):

pass**

對於dog來說,animal就是它的父類,對於animal來說,dog就是它的子類。cat和dog類似。

繼承有什麼好處?最大的好處是子類獲得了父類的全部功能。由於animial實現了run()方法,因此,dog和cat作為它的子類,什麼事也沒乾,就自動擁有了run()方法:

dog = dog()

dog.run()

cat = cat()

cat.run()

執行結果如下:

animal is running...

animal is running...

當然子類也可以自己增加def 方法

子類和父類都存在相同的run()方法時,我們說,子類的run()覆蓋了父類的run(),在**執行的時候,總是會呼叫子類的run()。這樣,我們就獲得了繼承的另乙個好處:多型。

要理解什麼是多型,我們首先要對資料型別再作一點說明。當我們定義乙個class的時候,我們實際上就定義了一種資料型別。我們定義的資料型別和python自帶的資料型別,比如str、list、dict沒什麼兩樣:

a = list() # a是list型別

b = animal() # b是animal型別

c = dog() # c是dog型別

繼承父類之後,c也是animal型別,這就是多型

繼承可以把父類的所有功能都直接拿過來,這樣就不必重零做起,子類只需要新增自己特有的方法,也可以把父類不適合的方法覆蓋重寫。

使用type()來判斷物件的型別很方便

對於class的繼承關係來說,使用type()就很不方便。我們要判斷class的型別,可以使用isinstance()函式。

isinstance(d, dog) and isinstance(d, animal)

true

能用type()判斷的基本型別也可以用isinstance()判斷:

isinstance(『a』, str)

true

isinstance(123, int)

true

isinstance(b』a』, bytes)

true

並且還可以判斷乙個變數是否是某些型別中的一種,比如下面的**就可以判斷是否是list或者tuple:

isinstance([1, 2, 3], (list, tuple))

true

isinstance((1, 2, 3), (list, tuple))

true

優先使用isinstance

如果要獲得乙個物件的所有屬性和方法,可以使用dir()函式,它返回乙個包含字串的list,比如,獲得乙個str物件的所有屬性和方法:(即對str物件可以進行哪些操作)

dir(『abc』)

[『add』, 『class』,…, 『subclasshook』, 『capitalize』, 『casefold』,…, 『zfill』]

**類似__***__的屬性和方法在python中都是有特殊用途的,比如__len__方法返回長度。在python中,如果你呼叫len()函式試圖獲取乙個物件的長度,實際上,在len()函式內部,它自動去呼叫該物件的__len__()方法,所以,下面的**是等價的:

> len('abc')

3> 'abc'.__len__()

3**

我們自己寫的類,如果也想用len(myobj)的話,就自己寫乙個__len__()方法:

class mydog(object):

… deflen(self):

… return 100

…dog = mydog()

len(dog)

100

配合getattr()、setattr()以及hasattr(),我們可以直接操作乙個物件的狀態:
# obj 是乙個只有x屬性的例項

>>> hasattr(obj, 'x') # 有屬性'x'嗎?

true

>>> obj.x

9>>> hasattr(obj, 'y') # 有屬性'y'嗎?

false

>>> setattr(obj, 'y', 19) # 設定乙個屬性'y'

>>> hasattr(obj, 'y') # 有屬性'y'嗎?

true

>>> getattr(obj, 'y') # 獲取屬性'y'

19>>> obj.y # 獲取屬性'y'

19

如果student類本身需要繫結乙個屬性呢?可以直接在class中定義屬性,這種屬性是類屬性,歸student類所有:

class student(object):

name = 『student』

當我們定義了乙個類屬性後,這個屬性雖然歸類所有,但類的所有例項都可以訪問到。來測試一下:

>>> class student(object):

... name = 'student'

...>>> s = student() # 建立例項s

>>> print(s.name) # 列印name屬性,因為例項並沒有name屬性,所以會繼續查詢class的name屬性

student

>>> print(student.name) # 列印類的name屬性

student

>>> s.name = 'michael' # 給例項繫結name屬性

>>> print(s.name) # 由於例項屬性優先順序比類屬性高,因此,它會遮蔽掉類的name屬性

michael

>>> print(student.name) # 但是類屬性並未消失,用student.name仍然可以訪問

student

>>> del s.name # 如果刪除例項的name屬性

>>> print(s.name) # 再次呼叫s.name,由於例項的name屬性沒有找到,類的name屬性就顯示出來了

student

例項屬性屬於各個例項所有,互不干擾;

類屬性屬於類所有,所有例項共享乙個屬性;

Python學習筆記 類的多繼承

類定義 class people 定義類的基本屬性 name age 0 weight 0 定義私有屬性,私有屬性在類外部無法直接進行訪問 def init self,name,age,grade self.name name self.age age self.grade grade defspe...

python基礎 繼承和多繼承

繼承 class a defspam self print a.spam defadd self,x,y return x y class b a defspam self 如果子類要對父類的方法進行重寫,再想呼叫父類的方法,就需要使用super 方法名 的形式 print b.spam super...

python基礎 繼承和多繼承

繼承 class a defspam self print a.spam defadd self,x,y return x y class b a defspam self 如果子類要對父類的方法進行重寫,再想呼叫父類的方法,就需要使用super 方法名 的形式 print b.spam super...