Python面向?qū)ο笕筇卣?封裝、繼承、多態(tài)
1、封裝
封裝: 根據(jù) 職責(zé) 將 屬性 和 方法 封裝到一個 抽象的類 中將數(shù)據(jù)(屬性)和行為(方法)包裝到類對象中。在方法內(nèi)部對屬性進行操作,在類對象的外部調(diào)用方法。這樣無需關(guān)心方法
- 內(nèi)部的具體實現(xiàn),從而隔離了復(fù)雜度
- 封裝是面向?qū)ο缶幊痰囊淮筇攸c
- 面向?qū)ο缶幊痰牡谝徊健傩院头椒ǚ庋b到一個抽象的類中
- 外界使用類創(chuàng)建對象,然后讓對象調(diào)用方法
- 對象方法的細節(jié)都封裝在類的內(nèi)部
:根據(jù)需求分析,完成案例

1 class Person:
2 def __init__(self,name,weight):
3self.name = name
4self.weight = weight
5
6 # 內(nèi)置函數(shù),可設(shè)置print打印輸出地址時的特定顯示,因此必須要有返回值
7 def __str__(self):
8return "我是%s,體重是%.1f公斤"%(self.name,self.weight)
9
10 def run(self):
11self.weight -= 0.5
12print("%s通過跑步體重減少"%self.name)
13 def eat(self):
14self.weight+=1
15print("%s吃太多,體重增加"%self.name)
16
17 p1 = Person("小明",65)
18 print(p1) #我是小明,體重是65.0公斤
19 p1.eat()#小明吃太多,體重增加
20 p1.run()#小明通過跑步體重減少
21 print(p1) #我是小明,體重是65.5公斤
22 print("*"*25)
23 p2 = Person("小美",45)
24 print(p2) #我是小美,體重是45.0公斤
25 p2.eat()#小美吃太多,體重增加
26 p2.run()#小美通過跑步體重減少
27 print(p2) #我是小美,體重是45.5公斤
28 print(p1) #我是小明,體重是65.5公斤

注意:在開發(fā)時,被使用的類需要先開發(fā)
1 #創(chuàng)建房子類
2 class House:
3 def __init__(self,house_type,area):
4self.house_type = house_type
5self.area = area
6self.free_area = area
7self.item_list = []
8
9 #添加家具
10 def add_item(self,item):
11#判斷面積是否足夠添加家具
12if item.area<self.free_area:
13 self.item_list.append(item.name)
14 self.free_area -= item.area
15 print("添加%s,占用面積%.1f"%(item.name,item.area))
16else:
17 print("面積不足無法添加")
18
19 #輸出房子打印
20 def __str__(self):
21#Python可以自動將一對括號內(nèi)的代碼連接到一起
22return ("該房子的戶型:%s\n總面積為:%.1f平米\n剩余面積為:%.1f平米\n家具:%s"
23 %(self.house_type,self.area,self.free_area,self.item_list))
24
25 #創(chuàng)建家具對象
26 jj1 = HouseItem("席夢思",4)
27 jj2 = HouseItem("衣柜",2)
28 jj3 = HouseItem("餐桌",1.5)
29 print(jj1)#家具席夢思,占地面積為:4.0平米
30 print(jj2)#家具衣柜,占地面積為:2.0平米
31 print(jj3)#家具餐桌,占地面積為:1.5平米
32 print("-"*30)
33 #創(chuàng)建房子對象,并添加家具
34 hs = House("大平層",6)
35 hs.add_item(jj1)
36 hs.add_item(jj2)
37 hs.add_item(jj3)
38 print("-"*30)
39 print(hs)
40
41 #運行結(jié)果
42 家具席夢思,占地面積為:4.0平米
43 家具衣柜,占地面積為:2.0平米
44 家具餐桌,占地面積為:1.5平米
45 ------------------------------
46 添加席夢思,占用面積4.0
47 面積不足無法添加
48 添加餐桌,占用面積1.5
49 ------------------------------
50 該房子的戶型:大平層
51 總面積為:6.0平米
52 剩余面積為:0.5平米
53 家具:['席夢思', '餐桌']
1.1 私有屬性和私有方法
提高程序的安全性:
在實際開發(fā)中,對象的某些屬性或方法只希望在類的內(nèi)部被使用,而不希望在外部被訪問到
在Python中沒有專門的修飾符用于屬性的私有,如果該屬性不希望在類對象外部被訪問,前面使用兩個“ _ ”(私有屬性)
在Python中其實并沒有真正的私有屬性、私有方法:
- 給屬性、方法命名時,實際是對名稱做了一些特殊處理,使得類對象無法直接訪問。
- 但是如果一定要從外界訪問私有屬性、私有方法的話,那么只需要在私有屬性、私有方法前加上_類名
例:stu_1._Student__age stu_1._Student__show_1()
注意:切記在開發(fā)時,不要以這種方式去訪問私有屬性和私有方法
1 #私有屬性、私有方法
2 class Student:
3 def __init__(self,name,age):
4self.name = name
5self.__age = age #使用(__屬性名)的方式將age聲明為私有屬性
6
7 def show(self):
8print(self.name,"的年齡為:",self.__age) #可以在類的內(nèi)部使用私有屬性
9
10 def __show_1(self): #使用(__方法名)的方式將show_1定義為私有方法
11print("這是{}的私有方法".format(self.name))
12
13 stu_1 = Student("張三",20)
14 stu_1.show() #由此可見可以在類的內(nèi)部使用私用屬性
15 print(stu_1.name)
16 #print(stu_1.__age) #代碼報錯,因為在類對象中并不能訪問類的私有屬性
17
18 #stu_1.__show_1() #代碼報錯,因為在類對象中并不能訪問類的私有屬性
19
20 """
21 在Python中起始并沒有真正的私有屬性、方法:
22 給屬性、方法命名時,實際是對名稱做了一些特殊處理,使得類對象無法直接訪問。
23 但是如果一定要從外界訪問私有屬性、方法的話,那么只需要在私有屬性、方法前加上_類名
24 例:stu_1._Student__age stu_1._Student__show_1()
25 """
26 print(stu_1._Student__age)
27 stu_1._Student__show_1()
28
29
運行結(jié)果:
張三 的年齡為: 20
張三
20
這是張三的私有方法
注意:
子類能繼承父類的私有屬性和私有方法
1 class A:
2 def __init__(self):
3self.num1 = 100
4self.__num2 = 200
5
6 def __fun(self):
7print("這是一個私有方法",self.__num2)
8
9 class B(A):
10 pass
11
12 b = B()
13 print(b._A__num2)
14 # print(b._b__num2) #代碼報錯,因為子類不能繼承父類的私有方法和私有屬性
15 b._A__fun()
16 # b._B__fun()
17 print(dir(b))
18 """
19 運行結(jié)果:
20 200
21 這是一個私有方法 200
22 ['_A__fun', '_A__num2', '__class__',
23 '__delattr__', '__dict__', '__dir__',
24 '__doc__', '__eq__', '__format__', '__ge__',
25 '__getattribute__', '__gt__', '__hash__',
26 '__init__', '__init_subclass__',
27 '__le__', '__lt__', '__module__',
28 '__ne__', '__new__', '__reduce__',
29 '__reduce_ex__', '__repr__', '__setattr__',
30 '__sizeof__', '__str__', '__subclasshook__',
31 '__weakref__', 'num1']
32 """
子類對象可以調(diào)用父類的公有方法,在父類的公有方法中調(diào)用父類的私有方法和私有屬性,那么子類對象就可以間接的使用該共有方法訪問父類的私有屬性和私有方法
2、繼承
- 實現(xiàn)代碼的重用,相同的代碼不需要重復(fù)編寫
- 繼承的語法格式
class 類名(父類名): pass
- 子類 繼承 父類,可以直接 享受 父類中已經(jīng)封裝好的方法,不需要再次開發(fā)
- 子類 中應(yīng)該根據(jù) 職責(zé),封裝 子類特有的 屬性和方法
- 繼承的傳遞性:子類擁有父類以及父類和父類中封裝的所有屬性和方法

1 #單繼承
2 class Animal:
3 def eat(self):
4print("吃")
5 def drink(self):
6print("喝")
7 def run(self):
8print("跑")
9 def sleep(self):
10print("睡")
11
12 class Dog(Animal):
13 def bark(self):
14print("叫")
15
16 class Cat(Animal):
17 def catch(self):
18print("抓老鼠")
19
20 class XiaoTianQuan(Dog):
21 def fly(self):
22print("飛")
23
24 xtq = XiaoTianQuan()
25 xtq.eat()
26 xtq.bark()
27 #xtq.catch() #報錯,因為xiaotianquan的父類及父類的父類都沒有該方法
2.1 方法的重寫
如果在子類中重寫了父類的方法,在子類對象調(diào)用方法時,會調(diào)用子類重寫的方法

1 #方法重寫
2 class Animal:
3 def eat(self):
4print("吃")
5 def drink(self):
6print("喝")
7 def run(self):
8print("跑")
9 def sleep(self):
10print("睡")
11
12 class Dog(Animal):
13 def bark(self):
14print("叫")
15
16 class Cat(Animal):
17 def catch(self):
18print("抓老鼠")
19
20 class XiaoTianQuan(Dog):
21 def fly(self):
22print("飛")
23
24 def bark(self):
25print("像神一樣的叫")
26
27 xtq = XiaoTianQuan()
28 xtq.bark()#像神一樣的叫
2.2 在子類方法中調(diào)用父類方法
- 方法一:使用
super().方法名 推薦使用 - 方法二:使用父類名.方法名
(self)在python2.x中 只能使用這個方式
1 #在子類方法中調(diào)用父類方法
2 class Animal:
3 def eat(self):
4print("動物吃")
5 def drink(self):
6print("動物喝")
7 def run(self):
8print("動物跑")
9 def sleep(self):
10print("動物睡")
11
12 class Dog(Animal):
13 def bark(self):
14print("狗叫")
15
16 class Cat(Animal):
17 def catch(self):
18print("抓老鼠")
19
20 class XiaoTianQuan(Dog):
21 def fly(self):
22print("像神一樣的飛")
23 def bark(self):
24#1.針對子類特有的需求,編寫的代碼
25print("像神一樣的叫")
26#2.方法一:使用super().調(diào)用原本封裝在父類中的方法
27super().bark()
28#3.方法二:使用super().調(diào)用原本封裝在父類中的方法
29Dog.bark(self)
30#4.增加子類其他的代碼
31print("------------------")
32 xtq = XiaoTianQuan()
33 xtq.bark()
34 """
運行結(jié)果:
像神一樣的叫
狗叫
狗叫
------------------
"""
2.3 多繼承
概念:
子類 可以擁有 多個父類,并且具有 所有父類的屬性 和 方法
例如:孩子 會繼承自己 父親 和 母親 的特性

1 #多繼承
2 class A:
3 def text(self):
4print("這是A類的text方法")
5 class B:
6 def fun(self):
7print("這是B類的fun方法")
8 class C(A,B):
9 pass
10 c = C()
11 c.text() #這是A類的text方法
12 c.fun()#這是B類的fun方法
注意事項:
如果 不同的父類 擁有相同的屬性名或者相同的方法名,子類對象在調(diào)用方法和屬性時,會調(diào)用那個父類的呢?
提示:在開發(fā)時,應(yīng)該盡量避免這種容易產(chǎn)生混淆的情況! ——如果父類之間存在同名屬性或者同名方法,應(yīng)該盡量避免使用
多繼承圖:

Python中的mro--方法搜索順序(了解)Python中針對 類 提供了一個內(nèi)置屬性__mro__可以查看 方法的搜索順序MRO是method tesolution order,主要用于 在多繼承判斷 方法 、屬性 的調(diào)用路徑- 子類對象在執(zhí)行父類的同名方法時,是按照
MRO輸出的從做到右的順序去執(zhí)行的
1 #多繼承屬性、方法同名
2 class A:
3 num = 100
4 def text(self):
5print("這是A類的text方法")
6 class B:
7 num = 200
8 def text(self):
9print("這是B類的fun方法")
10 class C(B,A):
11 pass
12 c_1 = C()
13 c_1.text()
14 print(c_1.num)
15 #確定C類對象的調(diào)用方法的路徑
16 print(C.__mro__)
17 """
18 運行結(jié)果:
19 這是B類的fun方法
20 200
21 (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
22 """
2.4 新式類和經(jīng)典類
object 是 Python 為所有對象提供的基類,提供有內(nèi)置的屬性和方法,可以使用dir來查看
1 class A(object): 2 pass 3 print(dir(A)) 4 5 """ 6 運行結(jié)果所顯示的屬性和方法都是由object提供的,因為我并沒有為A類設(shè)置任何的屬性和方法 7 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 8 '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', 9 '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', 10 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', 11'__str__', '__subclasshook__', '__weakref__'] 12 """
- 新式類:以
object為基類,推薦使用 - 經(jīng)典類:不以
object為基類,不推薦使用 - 在
python3.x中定義類,如果沒有指定父類,會默認使用object類作為該類的基類,因此,python3.x中所有的類都是新式類 - 在
python2.x中定義類,如果沒有指定父類,不會使用object作為基類。 - 經(jīng)典類和新式類在多繼承時——會影響到方法的搜索順序
為了保證編寫的代碼在Python2.x和Python3.x都能夠運行,在定義類的時,如果沒有父類,建議統(tǒng)一繼承object
class 類名(object): pass
3、多態(tài)
- 不同的對象,調(diào)用相同的方法,產(chǎn)生不同的執(zhí)行結(jié)果,增加代碼的靈活度
- 多態(tài)可以增加代碼的靈活度
- 以繼承和重寫父類方法為前提
- 是調(diào)用方法的技巧,不會影響到類的內(nèi)部設(shè)計
1 #多態(tài)的案例演示
2 """
3 1.定義Dog類,并中封裝方法game
4 普通的狗子蹦蹦跳跳
5 2.定義GodDog類,繼承自狗類,并重寫game方法
6 神狗在天上玩耍
7 3.定義ErHa類,繼承自狗類,并重寫game方法
8 傻狗在地上滾
9 4.定義Person類,并封裝一個和狗玩的方法game_with_dog方法
10 在方法內(nèi)部,直接讓 狗對象 調(diào)用game方法
11 """
12 class Dog(object):
13 def __init__(self,name):
14self.name = name
15
16 def game(self):
17print("蹦蹦跳跳")
18
19 class GodDog(Dog):
20 def game(self):
21print("%s在天上飛"%self.name)
22
23 class ErHa(Dog):
24 def game(self):
25print("%s這個傻狗在地上滾"%self.name)
26
27 class Person(object):
28 def __init__(self,name):
29self.name = name
30 def ame_with_dog(self,dog):
31print("%s在和%s玩耍"%(self.name,dog.name))
32dog.game()
33
34 #創(chuàng)建二哈
35 eh = ErHa("哈士奇")
36 #創(chuàng)建哮天犬
37 xtq = GodDog("哮天犬")
38 #創(chuàng)建二郎神
39 els = Person("二郎神")
40 els.ame_with_dog(eh)
41 print("*"*30)
42 els.ame_with_dog(xtq)
43 """
44 運行結(jié)果
45 二郎神在和哈士奇玩耍
46 哈士奇這個傻狗在地上滾
47 ******************************
48 二郎神在和哮天犬玩耍
49 哮天犬在天上飛
50 """
由上面代碼可以看出,二郎神在調(diào)用和狗玩的方法時,當(dāng)傳入的狗對象不同時,代碼的運行結(jié)果也不相同
到此這篇關(guān)于Python面向?qū)ο笕筇卣?封裝、繼承、多態(tài)的文章就介紹到這了,更多相關(guān)Python面向?qū)ο?封裝、繼承、多態(tài)內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非maisonbaluchon.cn所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。
關(guān)注官方微信