1、面向對象的概念
擁有共同屬性的一類進行歸類的過程叫做面向對象。
2、注意事項
class定義類的時候,類名的首字母必須大寫
3、面向對象案例
1 class Person(object): 2 def __init__(self,name,age): #name,age可以理解為類的屬性;init為初始化;類裡定義的函數稱為構造方法/構造函數 3 self.name=name #實例屬性 4 self.age=age 5 print("start") 6 def __del__(self): #清理操作 7 print("end") 8 def show(self): #self為類本身,不可省略 9 print("name:{0},age:{1}".format(self.name,self.age)) 10 obj=Person(name="wuya",age=18) #要調用類裡邊的變量、方法函數等,首先需要對類進行實例化;obj是類Person()實例化後的對象,類實例化的過程也是類初始化的過程。類的實例化過程也是針對構造方法初始化的過程(等於調用了__init__的方法) 11 obj.show() 12 #Person(name="wuya",age=18).show() #用類名調用方法
以上代碼運行的結果為:
4、類中方法的執行順序:初始化方法->具體的方法->清理的方法
5、面向對象的特性
1)封裝
a.實例屬性
b.數據屬性(類中的變量)
2)繼承
3)多態
6、方法:
a.普通方法:屬於對象,也屬於類,只能讀寫;
b.特性方法:屬於對象,只具備讀屬性,方法不能有形式參數;
c.靜態方法:屬於類,只能用類名來調用,一般把數據屬性使用靜態方法來處理
7、封裝入門實例
1 class Animal(object): 2 def __init__(self,age): 3 self.age=age 4 def getAge(self): 5 return self.age 6 def setAge(self,age): 7 if age>10 and age<100: 8 self.age=age #允許修改年齡 9 else: 10 print("年齡錯誤") 11 objAnimal=Animal(age=25) #類的實例化 12 print(objAnimal.getAge()) #輸出獲取年齡的方法的調用結果 13 objAnimal.setAge(age=11) #調用修改年齡的方法 14 print(objAnimal.getAge()) #輸出獲取年齡的方法的調用結果
8、封裝的進階實例
1 class Animal(object): 2 address="地球" #數據屬性 3 def __init__(self,age): 4 self.age=age #實例屬性 5 # @staticmethod 6 def address(self): #靜態方法,數據屬性使用靜態方法來處理 7 return "地球" 8 def show(self,name="*"): #普通方法,可讀寫 9 print("it come from {0},and it's age is {1},and it's name is {2}".format(self.address(),self.age,name)) 10 def func(self,**kwargs): 11 print(kwargs) 12 @property 13 def info(self): #特性方法,只讀(只有輸出) 14 print("hello world") 15 @property 16 def getAge(self): #特性方法,只讀(只有返回) 17 return self.age 18 objAnimal=Animal(age=30) #類的實例化 19 objAnimal.show() #調用普通方法 20 #objAnimal.show(name="monkey") 21 # Animal().show(name="monkey") 22 # Animal(age=10).address() 23 objAnimal.func(name="cch",age=18,city="西安") 24 objAnimal.info #特性方法調用 25 print(Animal.address("")) 26 print(objAnimal.age)
9、繼承
1)概念
父類(基類):被繼承的類
子類(派生類):繼承其他的類
2)Java和Python繼承的區別
Java是單繼承的,Python是多繼承的
3)子類繼承父類的什麼:
a、變量(數據屬性)
b、實例屬性
c、方法
3)方法重寫
當父類的方法沒有辦法滿足子類的需求的時候,子類就會重寫父類的方法,那麼子類實例化後的對象調用該方法,優先考慮的是子類的方法。
1 class Father(object): 2 address="西安" 3 def __init__(self,name,age): 4 self.name=name 5 self.age=age 6 def info(self): 7 print("this is a father's method") 8 class Son(Father): 9 def __init__(self,name,age,score): 10 Father.__init__(self,name,age) #子類繼承了父類的實例屬性 11 self.score=score 12 def show(self): 13 print("name is {0},and age is {1},and score is {1}".format(self.name,self.age,self.score)) 14 def info(self): #父類的方法重寫 15 print("this is a son's method") 16 son=Son(name="wuya",age=18,score=99) 17 son.show() 18 print(son.address) #子類繼承了父類的變量(數據屬性) 19 son.info() #不用print,info()中有print,函數與返回值時,輸出函數為空。子類重寫父類的方法,那麼子類實例化後的對象調用該方法,優先考慮的是子類的方法。
以上代碼運行的結果為:
10、繼承順序
1)從上到下(前提條件):
a.單個繼承
b.子類重寫了父類的方法
2)從左到右(前提條件):子類繼承多個類(子類可以繼承多個父類,但父類之間必須是同級關系。)
3)所以在Python中,基於MRO的解析順序規則,就會從左到右開始查找基類,如果找到第⼀個匹配的屬性類,就會停⽌查找,如果沒有,那就繼續查找,直到查找到符合要
求的為止。MRO其實就是通過⼀個C3線性化算法來實現的,它的核心思想為:
子類會優於父類檢查
多個父類會根據他們在列表中的順序被依次檢查
如果對下一個類存在兩個合法的選擇,只能選擇第一個(線性查找)
11、繼承順序示例
1 class Father(object): 2 def __init__(self,name,age): 3 self.name=name 4 self.age=age 5 def funM(self): 6 print("father") 7 8 class Mother(object): 9 def funM(self): 10 print("mother") 11 12 class Son(Father,Mother): #子類Son繼承了兩個父類 13 def __init__(self,name,age,score): 14 Father.__init__(self,name,age) #子類Son繼承了父類Father和Mother的實例屬性 15 self.score=score 16 17 son=Son(name="ccj",age=18,score=100) 18 son.funM() 19 print(Son.mro()) #使用類名調用mro,查看類的執行順序
以上代碼的執行結果為:
12、子類繼承多個非同級的父類錯誤示例
1 class Person(object): 2 pass 3 4 class Father(Person): 5 def __init__(self): 6 pass 7 def funM(self): 8 print("father") 9 class Mother(object): 10 def funM(self): 11 print("mother") 12 13 class Son(Person,Father): #子類繼承的多個父類不是同一級,代碼會報錯,z子類可以繼承多個父類,但父類之間必須是同級關系。
14 def __init__(self,score): 15 Father.__init__(self) 16 self.score=score 17 son=Son(score=90) 18 son.funM() 19 print(Son.mro())
以上代碼的運行結果為;
13、繼承方法調用錯誤示例
1 class Person(object): 2 pass 3 4 class Father(Person): 5 def __init__(self): 6 pass 7 8 class Mother(Person): 9 def funM(self): 10 print("mother") 11 12 class Son(Father): #子類繼承的父類中沒有funM方法,代碼會報錯 13 def __init__(self,score): 14 Father.__init__(self) 15 self.score=score 16 17 son=Son(score=99) 18 son.funM()
以上代碼的運行結果為:
14、繼承方法調用錯誤示例糾正
1 class Person(object): 2 def funM(self): 3 print("person") 4 5 class Father(Person): 6 def __init__(self): 7 pass 8 9 class Mother(Person): 10 def funM(self): 11 print("mother") 12 13 class Son(Father): #子類繼承法的父類是Father 14 def __init__(self,score): 15 Father.__init__(self) 16 self.score=score 17 18 son=Son(score=99) 19 son.funM() #子類調用方法,先從子類中查找,再從繼承的父類查找,若未找到,再從父類的父類中查找。 20 print(Son.mro())
以上方法的運行結果為:
15、繼承歷史問題
python2是深度優先,python3是廣度優先
1 class A: 2 def show(self): 3 print('A') 4 5 class B(A): 6 pass 7 8 class C(A): 9 def show(self): 10 print('C') 11 12 class D(B,C): 13 pass 14 15 if __name__ == '__main__': 16 obj=D() 17 obj.show() #python2執行的結果是A,pyhton3中的運行結果為C
16、多態
多太的優勢具體可以總結為如下幾點,具體為:
增加了持續的靈活性
增加了持續的額外擴展功能
1 class Animal(object): 2 def talk(self): 3 print("動物會叫") 4 5 class Dog(object): 6 def talk(self): 7 print("狗也會叫") 8 9 class Cat(object): 10 def talk(self): 11 print("貓也會叫") 12 13 def func(animal): 14 animal.talk() 15 if __name__ == '__main__': 16 dog=Dog() 17 func(animal=dog)
以上代碼的運行結果為: