比如,我們已經編寫了乙個名為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)能用type()判斷的基本型別也可以用isinstance()判斷:true
isinstance(『a』, str)並且還可以判斷乙個變數是否是某些型別中的一種,比如下面的**就可以判斷是否是list或者tuple:true
isinstance(123, int)
true
isinstance(b』a』, bytes)
true
isinstance([1, 2, 3], (list, tuple))優先使用isinstancetrue
isinstance((1, 2, 3), (list, tuple))
true
如果要獲得乙個物件的所有屬性和方法,可以使用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):配合getattr()、setattr()以及hasattr(),我們可以直接操作乙個物件的狀態:… deflen(self):
… return 100
…dog = mydog()
len(dog)
100
# 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...