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