Python之面向对象继承和派生
Python之面向對象繼承和派生
什么是繼承:
繼承是一種創建新的類的方法。在Python中,新建的類可以繼承自一個或多個父類。原始類稱為基類或超類。
新建的類稱為派生類或子類。
?
Python中類的繼承分為單繼承和多繼承。
class ParentClass1: #定義父類passclass ParentClass2: #定義父類passclass SubClass1(ParentClass1) #單繼承,基類是ParentClass,派生是SubClasspassclass SubClass2(ParentClass1,ParentClass2): #python支持多繼承,用逗號分隔開多個繼承的類。passprint(SubClass1.__bases__) #查看繼承的類。
注意:
如果沒有指定基類。Python的類會默認繼承object類。object是所有Python類的基類。他提供了一些常見方法。屁如:(__str__) 的實現。
?
繼承與抽象(先抽象再繼承):
抽象既抽取類似或者說比較像的部分。
抽象分為兩個層次:
1,將Obama和George這兩個對象比較像的部分抽取成類。
2,將人,猴,狗這三個類比較像的部分抽取成父類。
抽象最主要的作用是劃分類別。(可以隔離關注點,降低復雜度)
?
?
繼承:是基于抽象的結果,通過編程語言去實現它,肯定是先經歷抽象這個過程,才能通過繼承的方法去表達出抽象的結果。
抽象只是分析和設計的過程中,一個動作或者說一種技巧。通過抽象可以得到類。
多態:同一種事物的不同形態。人,狗都是動物。
?
?
繼承與重用性:
重用性:將重復的功能寫在父類里。在子類里繼承即可。
1 ==========================第一部分 2 例如 3 4 貓可以:喵喵叫、吃、喝、拉、撒 5 6 狗可以:汪汪叫、吃、喝、拉、撒 7 8 如果我們要分別為貓和狗創建一個類,那么就需要為 貓 和 狗 實現他們所有的功能,偽代碼如下: 9 10 11 #貓和狗有大量相同的內容 12 class 貓: 13 14 def 喵喵叫(self): 15 print '喵喵叫' 16 17 def 吃(self): 18 # do something 19 20 def 喝(self): 21 # do something 22 23 def 拉(self): 24 # do something 25 26 def 撒(self): 27 # do something 28 29 class 狗: 30 31 def 汪汪叫(self): 32 print '喵喵叫' 33 34 def 吃(self): 35 # do something 36 37 def 喝(self): 38 # do something 39 40 def 拉(self): 41 # do something 42 43 def 撒(self): 44 # do something 45 46 47 48 ==========================第二部分 49 上述代碼不難看出,吃、喝、拉、撒是貓和狗都具有的功能,而我們卻分別的貓和狗的類中編寫了兩次。如果使用 繼承 的思想,如下實現: 50 51 動物:吃、喝、拉、撒 52 53 貓:喵喵叫(貓繼承動物的功能) 54 55 狗:汪汪叫(狗繼承動物的功能) 56 57 偽代碼如下: 58 class 動物: 59 60 def 吃(self): 61 # do something 62 63 def 喝(self): 64 # do something 65 66 def 拉(self): 67 # do something 68 69 def 撒(self): 70 # do something 71 72 # 在類后面括號中寫入另外一個類名,表示當前類繼承另外一個類 73 class 貓(動物): 74 75 def 喵喵叫(self): 76 print '喵喵叫' 77 78 # 在類后面括號中寫入另外一個類名,表示當前類繼承另外一個類 79 class 狗(動物): 80 81 def 汪汪叫(self): 82 print '喵喵叫' 83 84 85 86 87 ==========================第三部分 88 #繼承的代碼實現 89 class Animal: 90 91 def eat(self): 92 print("%s 吃 " %self.name) 93 94 def drink(self): 95 print ("%s 喝 " %self.name) 96 97 def shit(self): 98 print ("%s 拉 " %self.name) 99 100 def pee(self): 101 print ("%s 撒 " %self.name) 102 103 104 class Cat(Animal): 105 106 def __init__(self, name): 107 self.name = name 108 self.breed = '貓' 109 110 def cry(self): 111 print('喵喵叫') 112 113 class Dog(Animal): 114 115 def __init__(self, name): 116 self.name = name 117 self.breed='狗' 118 119 def cry(self): 120 print('汪汪叫') 121 122 123 # ######### 執行 ######### 124 125 c1 = Cat('小白家的小黑貓') 126 c1.eat() 127 128 c2 = Cat('小黑的小白貓') 129 c2.drink() 130 131 d1 = Dog('胖子家的小瘦狗') 132 d1.eat() 133 134 使用繼承來重用代碼比較好的例子在開發程序的過程中,如果我們定義了一個類A,然后又想新建立另外一個類B,但是類B的大部分內容與類A的相同時
我們不可能從頭開始寫一個類B,這就用到了類的繼承的概念。
通過繼承的方式新建類B,讓B繼承A,B會‘遺傳’A的所有屬性(數據屬性和函數屬性),實現代碼重用
class Hero:def __init__(self,nickname,aggressivity,life_value):self.nickname=nicknameself.aggressivity=aggressivityself.life_value=life_valuedef move_forward(self):print('%s move forward' %self.nickname)def move_backward(self):print('%s move backward' %self.nickname)def move_left(self):print('%s move forward' %self.nickname)def move_right(self):print('%s move forward' %self.nickname)def attack(self,enemy):enemy.life_value-=self.aggressivity class Garen(Hero):passclass Riven(Hero):passg1=Garen('草叢倫',100,300) r1=Riven('銳雯雯',57,200)print(g1.life_value) r1.attack(g1) print(g1.life_value)''' 運行結果 '''提示:用已經有的類建立一個新的類,這樣就重用了已經有的軟件中的一部分設置大部分,大大生了編程工作量,這就是常說的軟件重用,不僅可以重用自己的類,也可以繼承別人的,比如標準庫,來定制新的數據類型,這樣就是大大縮短了軟件開發周期,對大型軟件開發來說,意義重大.
注意:像g1.life_value之類的屬性引用,會先從實例中找life_value然后去類中找,然后再去父類中找...直到最頂級的父類。
重點!!!:再看屬性查找
class Foo:def f1(self):print('Foo.f1')def f2(self):print('Foo.f2')self.f1()class Bar(Foo):def f1(self):print('Foo.f1')b=Bar() b.f2()?
派生:
首先要繼承一個父類,如果自己不定義自己的內容,那就從父類里拿。
如果在子類里定義和父類重名的東西,那么在調用時,以子類為準。
當然,也可以自己定義一個新的功能,父類沒有的功能。
?
如何在子類里派生的方法里,重用父類的邏輯:
?
? 如何在子類的方法里調用父類的方法。
?
#派生 class Hero:def __init__(self, nickname,aggressivity,life_value):self.nickname = nicknameself.aggressivity = aggressivityself.life_value = life_valuedef attack(self, enemy):print('Hero attack')class Garen(Hero):camp = 'Demacia'def attack(self, enemy): #self=g1,enemy=r1# self.attack(enemy) #g1.attack()Hero.attack(self,enemy) #用父類里的attack,參數是Hero里的attack的參數。這里的self是g1,enemy是r1print('from garen attack')def fire(self):print('%s is firing' % self.nickname)class Riven(Hero):camp = 'Noxus'g1 = Garen('garen', 18, 200) r1 = Riven('rivren', 18, 200) g1.attack(r1) # print(g1.camp) # print(r1.camp) # g1.fire()
?
在子類里,也定義init,這個init是和父類的init不沖突的。class Hero:
def __init__(self, nickname, aggressivity, life_value):self.nickname = nicknameself.aggressivity = aggressivityself.life_value = life_valuedef attack(self, enemy):print('Hero attack')enemy.life_value -= self.aggressivity
# print(Hero.__init__) # print(Hero.attack)
class Garen(Hero):camp = 'Demacia'def __init__(self, nickname, aggressivity, life_value, script):Hero.__init__(self,nickname,aggressivity,life_value) #調用父類的init方法,# self.nickname = nickname# self.aggressivity = aggressivity# self.life_value = life_valueself.script = script #也可以自己加自己的init。
def attack(self, enemy): # self=g1,enemy=r1# self.attack(enemy) #g1.attack() Hero.attack(self, enemy)print('from garen attack')
def fire(self):print('%s is firing' % self.nickname)
# g1=Garen('garen',18,200) #Garen.__init__(g1,'garen',18,200)
g1=Garen('garen',18,200,'人在塔在') #Garen.__init__(g1,'garen',18,200) print(g1.script)
?
組合:
? 多個類組合在一起。 解決代碼的重用性。是一種類與類之間與的關系。
?
class Teacher:def __init__(self,name,sex,course,birth):self.name = nameself.sex = sexself.course = courseself.birth = birthclass Student:def __init__(self,name,sex,course):self.name = nameself.sex = sexself.course = courseclass Course:def __init__(self,name,price,peroid):self.name = nameself.price = priceself.peroid = peroidpython_obj=Course('python',15800,'7m') t1=Teacher('egon','male',python_obj) s1=Student('cobila','male',python_obj)print(s1.course.name) print(t1.course.name)class Teacher:def __init__(self,name,sex,course_name,course_price,course_period):self.name=nameself.sex=sexself.course_name=course_nameself.course_price=course_priceself.course_period=course_periodclass Student:def __init__(self,name,sex,course_name,course_price,course_period):self.name=nameself.sex=sexself.course_name=course_nameself.course_price=course_priceself.course_period=course_periodt1=Teacher('egon','male','python',15800,'7m') s1=Student('cobila','male','python',15800,'7m')print(s1.course.name) print(t1.course.name)?
接口與歸一化設計:
接口:接口是對外入口,Python是沒有接口的概念的。所以Python只能用繼承去模擬Java的接口。
?
class Animal:def run(self):#主動拋異常raise AttributeError('子類必須實現這個方法')def speak(self):raise AttributeError('子類必須實現這個方法')class People(Animal):def run(self):print("Human is walk")def speak(self):print("man is tell")class Pig(Animal):def run(self):print('Pig is walking')def speak(self):print('Pig wow')peo1=People() # peo1.run() peo1.speak()# peo1=People() # pig1=Pig() # # peo1.run() # pig1.run()# class Interface:#定義接口Interface類來模仿接口的概念,python中壓根就沒有interface關鍵字來定義一個接口。 # def read(self): #定接口函數read # pass # # def write(self): #定義接口函數write # pass # # # class Txt(Interface): #文本,具體實現read和write # def read(self): # print('文本數據的讀取方法') # # def write(self): # print('文本數據的讀取方法') # # class Sata(Interface): #磁盤,具體實現read和write # def read(self): # print('硬盤數據的讀取方法') # # def write(self): # print('硬盤數據的讀取方法') # # class Process(Interface): # def read(self): # print('進程數據的讀取方法') # # def write(self): # print('進程數據的讀取方法')# t1=Txt() # s1=Sata() # p1=Process()# t1.read() # t1.write()# s1.read() # s1.write()# p1.read() # p1.write()
主動拋異常:
class Animal:def run(self):#主動拋異常raise AttributeError('子類必須實現這個方法')def speak(self):raise AttributeError('子類必須實現這個方法')?
抽象類:
本質還是類,與普通類額外的特點的是:加了裝飾器的函數,子類必須實現他們用abc模塊。
所有子類,必須實現父類中加了裝飾器函數的方法。否則無法實例。
import abc #抽象類:本質還是類,與普通類額外的特點的是:加了裝飾器的函數,子類必須實現他們 class Animal(metaclass=abc.ABCMeta):tag='123123123123123'@abc.abstractmethoddef run(self):pass@abc.abstractmethoddef speak(self):passclass People(Animal):def run(self):passdef speak(self):passpeo1=People() print(peo1.tag)?
?
轉載于:https://www.cnblogs.com/george92/p/9161788.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Python之面向对象继承和派生的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Powershell实现圆缩小放大 (实
- 下一篇: C# USB 摄像头 OpenCV 视频