Python面向对象之继承
面向?qū)ο笕筇匦?/strong>
單繼承
使用繼承前的代碼
class Animal:def eat(self):print("吃")def sleep(self):print("睡")class Dog:def eat(self):print("吃")def sleep(self):print("睡")def bark(self):print("犬吠")dog = Animal() dog.eat() dog.sleep()jinmao = Dog() jinmao.eat() jinmao.bark()雖然可以通過代碼復(fù)制來減少工作量,但代碼重復(fù)卻很多。
繼承的概念和語法
繼承的概念:子類擁有父類所有的屬性和方法;
繼承的語法
class 類名(父類名):pass- 子類繼承自父類,可以直接享用父類中已經(jīng)開發(fā)好的方法,不需要再次開發(fā);
- 子類中應(yīng)該根據(jù)職責(zé),封裝子類中特有的屬性和方法;
單繼承示例
class Animal:def eat(self):print("吃")def run(self):print("跑")def sleep(self):print("睡")class Dog(Animal):def bark(self):print("犬吠")jinmao = Dog() jinmao.eat() # 吃 jinmao.bark() # 叫繼承相關(guān)術(shù)語
子類=派生類;
父類=基類;
繼承=派生;
例如:
Dog類是Animal類的子類,Animal類是Dog類的父類,Dog類從Animal類繼承;
繼承的傳遞性
- C類繼承自B類,B類又繼承自A類;
- 那么C類就擁有B類和A類所有的屬性和方法;
- 總結(jié)就是:子類擁有父類及父類的父類的所有封裝的屬性與方法。
繼承傳遞示例
class Animal:def eat(self):print("吃")def run(self):print("跑")class Dog(Animal):def bark(self):print("犬吠")class Corgi(Dog):def leg(self):print("腿很短")keji = Corgi() # 子類使用自己的方法 keji.leg() # 子類使用父類的方法 keji.bark() # 子類使用父類的父類的方法 keji.eat()繼承傳遞的分支問題
雖然貓和狗都繼承自動物類,但狗的子類柯基并不能調(diào)用貓類的方法,因為柯基并沒有繼承自貓類;
方法重寫
應(yīng)用場景
- 當(dāng)父類中的方法滿足不了子類的需求時,可以對方法進行重寫;
- 重寫父類的方法有兩種:
1.覆蓋父類的方法;
2.對父類方法進行擴展;
覆蓋父類的方法
如果在開發(fā)中,父類的方法實現(xiàn)和子類的方法實現(xiàn),完全不同,就可以使用覆蓋在方法,在子類中重新編寫父類的方法實現(xiàn);
覆蓋方式:在子類中定義一個和父類重名的方法并且實現(xiàn);
重寫之后,在運行時,只會調(diào)用子類中重寫的方法,而不會再調(diào)用父類中封裝的方法;
class Dog(Animal):def bark(self):print("犬吠")class Corgi(Dog):def leg(self):print("腿很短")def bark(self):print("柯基吠")keji = Corgi() # 子類使用自己的方法 keji.leg() # 子類使用重寫父類的方法 keji.bark()子類中擴寫父類的方法
如果在開發(fā)中,子類的方法實現(xiàn),包含了父類的方法實現(xiàn),即原本父類封裝的方法是子類方法的一部分,這時候就可以使用子類擴寫父類的方法。
擴寫方式:
關(guān)于super
擴寫示例
class Dog(Animal):def bark(self):print("犬吠")class Corgi(Dog):def leg(self):print("腿很短")def bark(self):# 1.針對子類特有的需求,編寫代碼print("柯基吠")# 2.在需要的位置,調(diào)用父類的方法,用super().父類方法名super().bark()# 3.編寫子類方法其他的代碼print("...")keji = Corgi() # 子類使用自己的方法 keji.leg() # 子類使用 擴展父類的方法 keji.bark()# 腿很短 # 柯基吠 # 犬吠 # ...使用父類名調(diào)用父類方法(了解)
在python2.x中,如果需要調(diào)用父類的方法,還可以用這種方式:
父類名.方法(self)在python3中,仍然支持這種方法,但不推薦使用,因為一旦父類發(fā)生變化,調(diào)用位置的父類名同樣需要修改
注意:
使用父類名調(diào)用父類方法示例
class Dog(Animal):def bark(self):print("犬吠")class Corgi(Dog):def leg(self):print("腿很短")def bark(self):print("柯基吠")# 使用父類名調(diào)用父類方法,不推薦使用Dog.bark(self)# 注意,如果使用子類調(diào)用方法,會出現(xiàn)遞歸調(diào)用,形成死循環(huán)# Corgi.bark(self)print("...")keji = Corgi() keji.leg() keji.bark()# 腿很短 # 柯基吠 # 犬吠 # ...多繼承
多繼承概念和語法
概念:子類可以具有多個父類,并且具有多個父類的屬性和方法;
語法:
class 子類名(父類1,父類2,...):pass作用:多繼承可以讓子類同時具有多個父類的屬性和方法;
多繼承示例
class A:def test_a(self):print("test_a")class B:def test_b(self):print("test_b")class C(A, B):passc = C()c.test_a() # test_a c.test_b() # test_b多繼承注意事項
- 如果兩個父類之間具有同名屬性或方法,應(yīng)該盡量避免使用多繼承;
- 如果兩個父類之間具有同名屬性或方法,子類在調(diào)用方法時,會優(yōu)先使用先繼承那個父類的方法;
多繼承方法調(diào)用順序示例
class A:def test(self):print("test_a")def demo(self):print("demo_a")class B:def test(self):print("test_b")def demo(self):print("demo_b")class C(A, B):passc = C()c.test() # test_a c.demo() # demo_a我們把C的繼承父類順序換一下
class A:def test(self):print("test_a")def demo(self):print("demo_a")class B:def test(self):print("test_b")def demo(self):print("demo_b")class C(B, A):passc = C()c.test() # test_b c.demo() # demo_bMRO--方法搜索順序
__mro__的作用:在創(chuàng)建對象的類,以及繼承的父類中,查找要調(diào)用的方法的 順序;
- python中針對類提供了一個內(nèi)置屬性__mro__可以查看方法搜索順序;
- mro主要用于多繼承時,判斷方法,屬性的調(diào)用順序;
__mro__方法使用示例
# 假設(shè)C類繼承自B和A print(C.__mro__) 輸出結(jié)果: # (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)- 在搜索方法時,是按照__mro__搜索結(jié)果從左到右的順序查找的;
- 如果在當(dāng)前類中找到方法,就直接執(zhí)行,不再查找;
- 如果沒有找到,就查找下一個類中是否有對應(yīng)的方法,如果找到方法,就直接執(zhí)行,不再查找;
- 如果找到最后一個類,還沒有找到方法,就報錯。
__mro__方法使用完整示例
class A:def test(self):print("test_a")def demo(self):print("demo_a")class B:def test(self):print("test_b")def demo(self):print("demo_b")class C(B, A):passc = C()c.test() # test_b c.demo() # demo_b# 確定C類的調(diào)用方法順序 print(C.__mro__) # (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)新式類和經(jīng)典(舊式)類
- 在ipython中,添加了object就是新式類,沒添加就是經(jīng)典類;可以用dir(對象名)查看新式類和經(jīng)典類的內(nèi)置方法;
- 在ipython3下,就算你沒添加object,python解釋器也會給你加上,默認就是新式類;
object是python為所有對象提供的基類,提供有一些內(nèi)置的方法和屬性,可以用dir函數(shù)查看,dir(對象名);
新式類:以object為基類的類,推薦使用;
經(jīng)典類:不以object為基類的類,不推薦使用;
- 在python3中定義類時,如果沒有指定父類,會默認使用object作為該類的基類--python3中定義的類都是新式類;
- 在python2中,定義類時,如果沒有指定父類,則不會以object作為基類;
新式類和經(jīng)典類在多繼承時,會影響方法的搜索順序;
為了保證編寫的代碼能同時在python2和python3下運行,以后在定義類時,如果沒有父類,建議統(tǒng)一繼承object類;
class 類名(object):pass在ipython下查看內(nèi)置方法
查看新式類內(nèi)置方法
class A(object):passa = A() dir(a)查看舊式類內(nèi)置方法
class B:passb = B() dir(b)轉(zhuǎn)載于:https://www.cnblogs.com/yifchan/p/python-1-14.html
總結(jié)
以上是生活随笔為你收集整理的Python面向对象之继承的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux系统颜色默认表示的文件类型
- 下一篇: 由浅入深,走进Python装饰器----