第四十二篇 面对对象进阶
目錄
- 面對對象進階
- * 補充(數據類裝飾器:復制類中的數據屬性)
- 一、類的繼承
- 1.什么是繼承
- 2.為什么用繼承
- 3.對象的繼承
- 4.繼承與抽象
- 5.繼承的應用
- 6.對象查找屬性的順序
- 二、類的派生
- 1.派生
- 2.派生方法
- 三、類的組合
- 1.什么是組合
- 2.為什么用組合
- 3.如何使用組合
- 四、菱形繼承問題
- 1.類的分類
- 2.菱形繼承問題
- 3. C3算法與mro()方法
- 五、類的多態與多態性
面對對象進階
* 補充(數據類裝飾器:復制類中的數據屬性)
@dataclass只能在python3.7版本中使用
from dataclasses import dataclass @dataclass class Point:x: floaty: floatz: float = 0.0# p = Point(1.5, 2.5) # print(p) # produces "Point(x=1.5, y=2.5, z=0.0)" from dataclasses import dataclass@dataclass class zhuangbei:price: intaggrev: intlife_value: intbc = zhuangbei(9,100,10) class duolandun(zhuangbei):pass class BlackCleaver(zhuangbei):pass # print(bc) f = BlackCleaver(0,100,10) print(f) ''' BlackCleaver(price=0,aggrev=100,life_value=10) '''# https://www.cnblogs.com/apocelipes/p/10284346.html一、類的繼承
1.什么是繼承
1.繼承是一種新建類的方式。新建的類稱為子類,被繼承的類稱為父類
2.繼承的特性:子類會繼承父類所有的屬性
3.繼承其本質就是類與類之間的一種關系
class F_c:attri = '繼承'def __init__(self,name):self.name = namedef func(self):print('from 父類')class S_c(F_c):passson = S_c('son') print(son.attri) # 繼承數據屬性(可自行更改) print(son.name) # 繼承父類的屬性,即可以使用父類中的自定義屬性 son.func() # 繼承父類的函數屬性,即可以調用父類中的函數 ''' 繼承 son from 父類 '''2.為什么用繼承
可以避免重復代碼,即減少代碼的冗余
3.對象的繼承
1.python中支持一個類同時繼承多個父類
class Parent1:passclass Parent2:passclass Child(Parent1, Parent2):pass**2.使用__bases__方法可以獲取對象所繼承的類**
print(child.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>) # 是一個元組,所以我們可以通過for循環打印 for i in child.__bases__:print(i)4.繼承與抽象
1.繼承描述的是子類與父類之間的關系,要找出它們的關系,必須先抽象再繼承。抽象:抽取類似或者說比較像的部分
2.抽象主要的作用是劃分類別(可以隔離關注點,降低復雜度)
3.抽象只是分析和設計過程的一個動作,或者說是一種技巧,通過抽象,我們可以得到類
- 1.抽象過程
- 2.抽象結果
5.繼承的應用
class SchoolPeople:school = 'XXschool'def __init__(self,name,age,gender):self.name = nameself.age = ageself.gender = genderclass Student(SchoolPeople):def choose_course(self):print(f'{self.name} is choose course')class Teacher(SchoolPeople):def mark(self, stu_obj, score):print('{self.name} is mark')stu_obj.grade = score # 對象本質上可以看作是一個字典,所以可以直接添加(對象是可以點出屬性的)stud = Student('king',26,'male') print(stud.__dict__) teac = Teacher('teacher',27,'male') print(teac.__dict__)stud.choose_course() teac.mark(stud,100) print(stud.__dict__) print(teac.__dict__)''' {'name': 'king', 'age': 26, 'gender': 'male'} {'name': 'teacher', 'age': 27, 'gender': 'male'} king is choose course teacher is mark {'name': 'king', 'age': 26, 'gender': 'male', 'grade': 100} {'name': 'teacher', 'age': 27, 'gender': 'male'} '''6.對象查找屬性的順序
對象自己 ----> 對象的類 ----> 父類 ----> 父類(如果存在多個父類).... ----> 爺爺類
class Foo:def f1(self):print('f1 of Foo ')def f2(self):print('f2 of Foo ')self.f1() # 這里的self指的是實例化對象(千萬不要看作是f2)class Bar(Foo):def f1(self):print('f1 of Bar')obj = Bar() # 實例化一個對象obj.f2() # 對象查找屬性的路徑:對象自己--》對象的類--》父類... ''' 所以 obj.f2() 的結果為: f2 of Foo f1 of Bar '''二、類的派生
1.派生
派生:子類中定義新的屬性的過程叫做派生。子類在使用派生的屬性時,始終以自己的派生屬性為準
2.派生方法
方法一:指名道姓訪問某一個類中的函數,與繼承無關(子類自己定義屬性)
class SchoolPeople:school = 'XXschool'def __init__(self,name,age,gender):self.name = nameself.age = ageself.gender = genderclass Teacher(SchoolPeople):def __init__(self,name,age,gender,level):SchoolPeople.__init__(self,name,age,gender)self.level = leveldef mark(self, stu_obj, score):print('{self.name} is mark')teac = Teacher('king',26,'male',2) print(teac.__dict__) # {'name': 'king', 'age': 26, 'gender': 'male', 'level': 2}方法二:
1.嚴格以繼承屬性來查找關系(可以參考菱形繼承問題)
**2.利用super().__init__方法進行派生子類的新屬性**
3.super()會得到一個特殊的對象,該對象就是專門用來訪問分類中的屬性的(按照繼承關系來查找屬性)
4.python2中的語法:super(自己的類名,self)。python3中的語法:super()
class SchoolPeople:school = 'XXschool'def __init__(self,name,age,gender):self.name = nameself.age = ageself.gender = genderclass Teacher(SchoolPeople):def __init__(self,name,age,gender,level):super().__init__(self,name,age,gender)# python2語法:# super(Teacher,self).__init__(self,name,age,gender)self.level = leveldef mark(self, stu_obj, score):print('{self.name} is mark')teac = Teacher('king',26,'male',2) print(teac.__dict__) # {'name': 'king', 'age': 26, 'gender': 'male', 'level': 2}三、類的組合
1.什么是組合
在一個類中以另外一個類的對象作為數據屬性
2.為什么用組合
組合可以解決類與類之間代碼冗余的問題
3.如何使用組合
class SchoolPeople:def __init__(self, name, age, gender):self.name = nameself.age = ageself.gender = genderdef login(self):print(f'{self.name}登陸')class Student(SchoolPeople):def __init__(self, id, name, age, gender):self.id = idsuper(Student, self).__init__(name, age, gender) # python2 語法def choose(self, course):print(f'{self.name}選擇了{course.name}課程')king = Student(1, 'king', 26, 'male')class Teacher(SchoolPeople):def __init__(self, name, age, gender, level):super().__init__(name, age, gender) # python3 語法self.level = leveldef scored(self, student, course, score):print(f'老師{self.name}給學生{student.name}的{course.name}課程打了{score}分')nick = Teacher('nick',20,'male',1) class Course:def __init__(self, name, price):self.name = nameself.price = pricepython = Course('python', 8888)# 類的組合:將另一個類的對象當作這個類的數據屬性 class Admin(SchoolPeople, Course):# 組合的應用def creat_course(self, name, price):res = Course(name, price) # 通過類中的方法調用其他的類(生成一個實例對象)print(f'{self.name}創建了課程{res.name}')return res # 返回被調用類運行的結果,這個結果就是一個實例對象egon = Admin('egon', 20, 'male') python = egon.creat_course('python', 20000) # 相當于在類內部調用另一個類,同樣可以實例化對象 print(python.price)四、菱形繼承問題
1.類的分類
1.1 新式類
1.繼承了object的類以及該類的子類的類,都是新式類
2.python3中所有的類都是新式類
1.2 經典類
1.沒有繼承object的類以及該類的子類,都是經典類
2.只有python2中有經典類
2.菱形繼承問題
1.1經典類:深度優先
1.2新式類:廣度優先
3. C3算法與mro()方法
3.1 對于python中定義的每個類,python會計算出一個方法解析順序列表(MRO),這個MRO列表就是一個簡單的所有基類的線性順序列表
3.2 通過mro()方法,我們可以得到新式類的尋找屬性順序
class A:passclass B(A):passclass C(A):passclass D(A):passclass E(D):passclass F(C):passclass G(B,E,F):passprint(G.mro()) ''' [<class '__main__.G'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.D'>, <class '__main__.F'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] '''for i in G.mro():print(i) ''' <class '__main__.G'> <class '__main__.B'> <class '__main__.E'> <class '__main__.D'> <class '__main__.F'> <class '__main__.C'> <class '__main__.A'> <class 'object'> '''為了實現繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類為止。
而這個MRO列表的構造是通過一個C3線性化算法來實現的。我們不去深究這個算法的數學原理,它實際上就是合并所有父類的MRO列表并遵循如下三條準則:
五、類的多態與多態性
1.多態:多種狀態,只要大家能繼承同一種東西A,這些東西就是A的多態
2.水:液態/固態/氣態
3.動物:人/狗/貓
4.總結
4.1 鴨子類型:長得像鴨子,叫聲也像鴨子,就是鴨子,(只要有speak和eat這兩個方法,那他就是動物類)
4.2 對于我們這個例子:==你只要有speak方法/有eat方法,我無論你怎么定義這個類,你就是動物==的一種形態,你這樣才能用動物的方法,否則無法使用動物的方法
5.多態性的好處(涉及到接口)
Python本身就是多態,根本就不支持多態
class Animal():def eat(self):print('eat')class People(Animal):def eat(self):print('人吃') class Dog(Animal):def eat(self):print('?吃') class Pig(Animal):def eat(self):print('?吃')def sleep(self):print('?睡') class F(Animal):def eat(self):print('f吃') f = F()peo = People() pig = Pig() dog = Dog()# 多態性 peo.eat() pig.eat() dog.eat() f.eat()class Cat(Animal):def eat(self):print('?ᄆ吃') cat = Cat() cat.eat()# 100種動物 print('*'*50) # 多態性的使用,提供接口的概念 def func(obj):obj.eat()obj.run()obj.walk()obj.sleep()func(cat) # cat.eat() # cat.walk() # cat.run() # cat.sleep() func(dog) # dog.eat() # dog.walk() # dog.run() # dog.sleep() func(peo)取錢,插卡-》輸入密碼-》輸入金額-》取到錢了
(插卡-》輸入密碼-》輸入金額-》取到錢了)--》取錢函數
鴨子類型:只要長得像?,叫的像?,游泳也想?,你就是?
參考鏈接:http://www.cnblogs.com/nickchen121/
轉載于:https://www.cnblogs.com/itboy-newking/p/11072034.html
總結
以上是生活随笔為你收集整理的第四十二篇 面对对象进阶的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring boot环境准备及搭建
- 下一篇: Spring Boot的学习之路(03)