第四十二篇 面对对象进阶
目錄
- 面對(duì)對(duì)象進(jìn)階
- * 補(bǔ)充(數(shù)據(jù)類(lèi)裝飾器:復(fù)制類(lèi)中的數(shù)據(jù)屬性)
- 一、類(lèi)的繼承
- 1.什么是繼承
- 2.為什么用繼承
- 3.對(duì)象的繼承
- 4.繼承與抽象
- 5.繼承的應(yīng)用
- 6.對(duì)象查找屬性的順序
- 二、類(lèi)的派生
- 1.派生
- 2.派生方法
- 三、類(lèi)的組合
- 1.什么是組合
- 2.為什么用組合
- 3.如何使用組合
- 四、菱形繼承問(wèn)題
- 1.類(lèi)的分類(lèi)
- 2.菱形繼承問(wèn)題
- 3. C3算法與mro()方法
- 五、類(lèi)的多態(tài)與多態(tài)性
面對(duì)對(duì)象進(jìn)階
* 補(bǔ)充(數(shù)據(jù)類(lèi)裝飾器:復(fù)制類(lèi)中的數(shù)據(jù)屬性)
@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一、類(lèi)的繼承
1.什么是繼承
1.繼承是一種新建類(lèi)的方式。新建的類(lèi)稱(chēng)為子類(lèi),被繼承的類(lèi)稱(chēng)為父類(lèi)
2.繼承的特性:子類(lèi)會(huì)繼承父類(lèi)所有的屬性
3.繼承其本質(zhì)就是類(lèi)與類(lèi)之間的一種關(guān)系
class F_c:attri = '繼承'def __init__(self,name):self.name = namedef func(self):print('from 父類(lèi)')class S_c(F_c):passson = S_c('son') print(son.attri) # 繼承數(shù)據(jù)屬性(可自行更改) print(son.name) # 繼承父類(lèi)的屬性,即可以使用父類(lèi)中的自定義屬性 son.func() # 繼承父類(lèi)的函數(shù)屬性,即可以調(diào)用父類(lèi)中的函數(shù) ''' 繼承 son from 父類(lèi) '''2.為什么用繼承
可以避免重復(fù)代碼,即減少代碼的冗余
3.對(duì)象的繼承
1.python中支持一個(gè)類(lèi)同時(shí)繼承多個(gè)父類(lèi)
class Parent1:passclass Parent2:passclass Child(Parent1, Parent2):pass**2.使用__bases__方法可以獲取對(duì)象所繼承的類(lèi)**
print(child.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>) # 是一個(gè)元組,所以我們可以通過(guò)for循環(huán)打印 for i in child.__bases__:print(i)4.繼承與抽象
1.繼承描述的是子類(lèi)與父類(lèi)之間的關(guān)系,要找出它們的關(guān)系,必須先抽象再繼承。抽象:抽取類(lèi)似或者說(shuō)比較像的部分
2.抽象主要的作用是劃分類(lèi)別(可以隔離關(guān)注點(diǎn),降低復(fù)雜度)
3.抽象只是分析和設(shè)計(jì)過(guò)程的一個(gè)動(dòng)作,或者說(shuō)是一種技巧,通過(guò)抽象,我們可以得到類(lèi)
- 1.抽象過(guò)程
- 2.抽象結(jié)果
5.繼承的應(yīng)用
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 # 對(duì)象本質(zhì)上可以看作是一個(gè)字典,所以可以直接添加(對(duì)象是可以點(diǎn)出屬性的)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.對(duì)象查找屬性的順序
對(duì)象自己 ----> 對(duì)象的類(lèi) ----> 父類(lèi) ----> 父類(lèi)(如果存在多個(gè)父類(lèi)).... ----> 爺爺類(lèi)
class Foo:def f1(self):print('f1 of Foo ')def f2(self):print('f2 of Foo ')self.f1() # 這里的self指的是實(shí)例化對(duì)象(千萬(wàn)不要看作是f2)class Bar(Foo):def f1(self):print('f1 of Bar')obj = Bar() # 實(shí)例化一個(gè)對(duì)象obj.f2() # 對(duì)象查找屬性的路徑:對(duì)象自己--》對(duì)象的類(lèi)--》父類(lèi)... ''' 所以 obj.f2() 的結(jié)果為: f2 of Foo f1 of Bar '''二、類(lèi)的派生
1.派生
派生:子類(lèi)中定義新的屬性的過(guò)程叫做派生。子類(lèi)在使用派生的屬性時(shí),始終以自己的派生屬性為準(zhǔn)
2.派生方法
方法一:指名道姓訪(fǎng)問(wèn)某一個(gè)類(lèi)中的函數(shù),與繼承無(wú)關(guān)(子類(lèi)自己定義屬性)
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.嚴(yán)格以繼承屬性來(lái)查找關(guān)系(可以參考菱形繼承問(wèn)題)
**2.利用super().__init__方法進(jìn)行派生子類(lèi)的新屬性**
3.super()會(huì)得到一個(gè)特殊的對(duì)象,該對(duì)象就是專(zhuān)門(mén)用來(lái)訪(fǎng)問(wèn)分類(lèi)中的屬性的(按照繼承關(guān)系來(lái)查找屬性)
4.python2中的語(yǔ)法:super(自己的類(lèi)名,self)。python3中的語(yǔ)法: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語(yǔ)法:# 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}三、類(lèi)的組合
1.什么是組合
在一個(gè)類(lèi)中以另外一個(gè)類(lèi)的對(duì)象作為數(shù)據(jù)屬性
2.為什么用組合
組合可以解決類(lèi)與類(lèi)之間代碼冗余的問(wèn)題
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 語(yǔ)法def choose(self, course):print(f'{self.name}選擇了{(lán)course.name}課程')king = Student(1, 'king', 26, 'male')class Teacher(SchoolPeople):def __init__(self, name, age, gender, level):super().__init__(name, age, gender) # python3 語(yǔ)法self.level = leveldef scored(self, student, course, score):print(f'老師{self.name}給學(xué)生{student.name}的{course.name}課程打了{(lán)score}分')nick = Teacher('nick',20,'male',1) class Course:def __init__(self, name, price):self.name = nameself.price = pricepython = Course('python', 8888)# 類(lèi)的組合:將另一個(gè)類(lèi)的對(duì)象當(dāng)作這個(gè)類(lèi)的數(shù)據(jù)屬性 class Admin(SchoolPeople, Course):# 組合的應(yīng)用def creat_course(self, name, price):res = Course(name, price) # 通過(guò)類(lèi)中的方法調(diào)用其他的類(lèi)(生成一個(gè)實(shí)例對(duì)象)print(f'{self.name}創(chuàng)建了課程{res.name}')return res # 返回被調(diào)用類(lèi)運(yùn)行的結(jié)果,這個(gè)結(jié)果就是一個(gè)實(shí)例對(duì)象egon = Admin('egon', 20, 'male') python = egon.creat_course('python', 20000) # 相當(dāng)于在類(lèi)內(nèi)部調(diào)用另一個(gè)類(lèi),同樣可以實(shí)例化對(duì)象 print(python.price)四、菱形繼承問(wèn)題
1.類(lèi)的分類(lèi)
1.1 新式類(lèi)
1.繼承了object的類(lèi)以及該類(lèi)的子類(lèi)的類(lèi),都是新式類(lèi)
2.python3中所有的類(lèi)都是新式類(lèi)
1.2 經(jīng)典類(lèi)
1.沒(méi)有繼承object的類(lèi)以及該類(lèi)的子類(lèi),都是經(jīng)典類(lèi)
2.只有python2中有經(jīng)典類(lèi)
2.菱形繼承問(wèn)題
1.1經(jīng)典類(lèi):深度優(yōu)先
1.2新式類(lèi):廣度優(yōu)先
3. C3算法與mro()方法
3.1 對(duì)于python中定義的每個(gè)類(lèi),python會(huì)計(jì)算出一個(gè)方法解析順序列表(MRO),這個(gè)MRO列表就是一個(gè)簡(jiǎn)單的所有基類(lèi)的線(xiàn)性順序列表
3.2 通過(guò)mro()方法,我們可以得到新式類(lèi)的尋找屬性順序
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'> '''為了實(shí)現(xiàn)繼承,python會(huì)在MRO列表上從左到右開(kāi)始查找基類(lèi),直到找到第一個(gè)匹配這個(gè)屬性的類(lèi)為止。
而這個(gè)MRO列表的構(gòu)造是通過(guò)一個(gè)C3線(xiàn)性化算法來(lái)實(shí)現(xiàn)的。我們不去深究這個(gè)算法的數(shù)學(xué)原理,它實(shí)際上就是合并所有父類(lèi)的MRO列表并遵循如下三條準(zhǔn)則:
五、類(lèi)的多態(tài)與多態(tài)性
1.多態(tài):多種狀態(tài),只要大家能繼承同一種東西A,這些東西就是A的多態(tài)
2.水:液態(tài)/固態(tài)/氣態(tài)
3.動(dòng)物:人/狗/貓
4.總結(jié)
4.1 鴨子類(lèi)型:長(zhǎng)得像鴨子,叫聲也像鴨子,就是鴨子,(只要有speak和eat這兩個(gè)方法,那他就是動(dòng)物類(lèi))
4.2 對(duì)于我們這個(gè)例子:==你只要有speak方法/有eat方法,我無(wú)論你怎么定義這個(gè)類(lèi),你就是動(dòng)物==的一種形態(tài),你這樣才能用動(dòng)物的方法,否則無(wú)法使用動(dòng)物的方法
5.多態(tài)性的好處(涉及到接口)
Python本身就是多態(tài),根本就不支持多態(tài)
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()# 多態(tài)性 peo.eat() pig.eat() dog.eat() f.eat()class Cat(Animal):def eat(self):print('?ᄆ吃') cat = Cat() cat.eat()# 100種動(dòng)物 print('*'*50) # 多態(tài)性的使用,提供接口的概念 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)取錢(qián),插卡-》輸入密碼-》輸入金額-》取到錢(qián)了
(插卡-》輸入密碼-》輸入金額-》取到錢(qián)了)--》取錢(qián)函數(shù)
鴨子類(lèi)型:只要長(zhǎng)得像?,叫的像?,游泳也想?,你就是?
參考鏈接:http://www.cnblogs.com/nickchen121/
轉(zhuǎn)載于:https://www.cnblogs.com/itboy-newking/p/11072034.html
總結(jié)
以上是生活随笔為你收集整理的第四十二篇 面对对象进阶的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: spring boot环境准备及搭建
- 下一篇: JVM内存堆布局图解分析