靈魂三問
什么是繼承?
繼承是一種創建新的類的方式,新創建的叫子類,繼承的叫父類、超類、基類。
特點:子類可以使用父類的屬性(特征、技能)
繼承是類與類之間的關系
為什么要繼承?
減少代碼冗余、提高重用性
如何用繼承?
單繼承
class grandFather():
print('我是爺爺')
class Parent(grandFather):
print('我是父類')
class SubClass(Parent):
print('我是子類')
sub = SubClass()
#結果:我是爺爺
# 我是父類
# 我是子類
#注意:類在定義的時候就執行類體代碼,執行順序是從上到下
多繼承
class Parent2():
print('我是第二個爹')
class Parent():
print('我是第一個爹')
class SubClass(Parent, Parent2):
print('我是子類')
#
# 結果:我是第二個爹
# 我是第一個爹
# 我是子類
#注意:類在定義的時候就執行類體代碼,執行順序是從上到下
-
使用__bases__方法可以獲取子類繼承的類
class Parent2(): print('我是第二個爹') class Parent(): print('我是第一個爹') class SubClass(Parent, Parent2): print('我是子類') print(SubClass.__bases__) #注意,如果sub = SubClass(),sub是沒有__bases__方法的
新式類、經典類
-
繼承了object的類以及該類的子類,都是新式類。
在Python3中如果一個類沒有繼承任何類,則默認繼承object類。因此python3中都是新式類
-
沒有繼承object的類以及該類的子類,都是經典類。
在Python2中如果一個類沒有繼承任何類,不會繼承object類。因此,只有Python2中有經典類。
繼承與抽象
抽象:通過抽象可以得到類,抽象是一種分析的過程。例如:從小豬佩奇、豬八戒、豬剛鬣、豬豬俠這些具體的對象中,可以分析一下,抽象出一個類,這個類就是豬類。接着,可以從豬、貓、狗等中,可以抽象出一個動物類。先分析、抽象之后,就可以通過繼承,在程序上實現這個結構。
class Animals:
pass
class Pig(Animals):
pass
class Dog(Animals):
pass
class Cat(Animals):
pass
派生類
概念:派生,就是在子類繼承父類的屬性的基礎上,派生出自己的屬性。子類有不同於父類的屬性,這個子類叫做派生類。通常情況下,子類和派生類是同一個概念,因為子類都是有不同於父類的屬性,如果子類和父類屬性相同,就沒必要創建子類了。
class Animals:
pass
class Dog(Animals):
pass
#這時候Dog類不是派生類
class Animals:
def __init__(self, name):
self.name = name
def walk(self):
print('我會走')
class Dog(Animals):
#Dog類派生出bite功能
#派生:狗有咬人的技能
def bite(self):
print('我會咬人')
組合
除了繼承之外,還有一種提高重用性的方式:組合
組合指的是,在一個類A中,使用另一個類B的對象作為類A的數據屬性(特征)(變量),成為類的組合。
#例子:人和手機,人想要有打電話的功能,想要打電話,就需要用到手機,人想要用到手機里面的打電話功能,肯定不能用繼承,人繼承手機就非常尷尬了,這時候就可以用到組合。
class Mobile():
def __init__(self, color):
self.color = color
def call(self):
print('老子可以打電話')
class People():
def __init__(self, name, mobile):
self.name = name
self.mobile = mobile
mobile = Mobile('yellow')
people = People('小白', mobile)
people.mobile.call()
#結果:老子可以打電話
繼承建立了派生類和基類的關系,是一種是的關系,比如白馬是馬,人是動物。
組合建立了兩個類之間'有'的關系,比如人有手機,然后人可以使用手機打電話。
屬性查找順序
對象查找屬性的順序:對象自己的 - > 所在類中 -> 找父類 - >父類的父類 ->Object
覆蓋
也稱之為重寫 overrides
當子類出現了與父類名稱完全一致的屬性或是方法
子類中訪問父類的內容
方式1:
super(當前類名稱,self).你要調的父類的屬性或方法
方式2:
super().你要調的父類的屬性或方法
方式3:
類名稱.你要調的父類的屬性或方法(self)
強調在強調:
當你繼承一個現有的類,並且你覆蓋了父類的init方法時,必須在初始化方法的第一行調用父類的初始化方法,並傳入父類所需的參數
類的mro方法
mro方法可以列出類繼承的所有父類,並且有順序。調用mro方法要用類名.mro
菱形繼承
類的繼承圖是從一個類開始繼承,繼承到頂點時,多個類繼承同一個頂點,這種就叫做菱形繼承。菱形繼承查找類時就用廣度查找。什么叫廣度查找呢?TMD, 不想寫了。
遇到共同父類時就廣度
經典類都是深度優先