目錄python
面向對象階段最重要的知識點:json
繼承指的是定義類的方法,新定義的類稱之爲子類或者派生類函數
子類繼承的類叫作父類,也叫基類/超類3d
繼承的特性:code
減小代碼的冗餘(減小重複代碼)。對象
首先肯定好誰是子類,誰是父類blog
在定義類時,子類(),()內寫上父類名,實現繼承繼承
繼承初體驗:utf-8
# 父類1 class ParentClass1: pass # 父類2 class ParentClass2: pass # 子類1 class SubClass1(ParentClass1): # 繼承父類1 pass # 子類2 class SubClass2(ParentClass1,ParentClass2): # 繼承父類1,父類2 pass # 查看繼承的父類:__bases__是類的屬性,用來查找當前類的父類 print(SubClass1.__bases__) # (<class '__main__.ParentClass1'>,) print(SubClass2.__bases__) # (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
要想尋找繼承關係,首先要「先抽象,在繼承」開發
抽象是一種思想
奧巴馬 --> 屬於人類 --> 屬於動物類
哈士奇 --> 屬於狗類 --> 屬於動物類
把相同的屬性(特徵和技能)抽象出來,定義動物類,稱之爲父類。
動物類:
特徵:
眼睛、鼻子、耳朵
技能:
吃、喝、拉、撒
繼承在程序中實現
奧巴馬 (對象)--> 調用人類 --> 繼承動物類
哈士奇 (對象)--> 調用狗類 --> 繼承動物類
上代碼
# 父類 class OldboyPeople: # 定義相同的屬性 school = "oldboy" def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex class OldboyTeacher(OldboyPeople): def change_score(self): print(f"老師{self.name} 修改分數") class OldboyStudent(OldboyPeople): def choose_course(self): print(f"學生{self.name}選擇課程") stu1 = OldboyStudent("qinyj",18,"female") tea1 = OldboyTeacher("tank",18,"female") print(stu1.name,stu1.age,stu1.sex) print(tea1.name,tea1.age,tea1.sex)
在繼承背景下,對象屬性的查找順序爲:
對象查找屬性會先從對象的名稱呢過空間中查找
若對象中沒有,則會去類裏面查找
若當前子類裏面有就返回,若是沒有會去父類裏面找
注意:若子類定義和父類相同的屬性,會優先使用子類的。
# 驗證對象屬性的查找順序: class Foo: def f1(self): print("Foo.f1") def f2(self): print("Foo.f2") self.f1() class Soo(Foo): def f1(self): print("Soo.f1") s = Soo() s.f2() # Foo.f2 # Soo.f1 # Soo-->Foo 在Soo類中從新定義了f1方法,此時優先使用子類中的f1方法,這時候對象去子類的名稱空間裏找就會找到,打印Soo.f1 # 查看對象名稱空間 __dict__ print(s.__dict__) # __class__:查看對象的屬性,查看當前對象的類 print(s.__class__) # <class '__main__.Soo'> # 查看子類名稱空間 print(s.__class__.__dict__) # {'__module__': '__main__', 'f1': <function Soo.f1 at 0x0000000009FF3BF8>, '__doc__': None} # 查看父類的名稱空間 # __bases__:查看繼承的父類 print(s.__class__.__bases__[0].__dict__) # {'__module__': '__main__', 'f1': <function Foo.f1 at 0x0000000009FF3B70>, 'f2': <function Foo.f2 at 0x0000000009FF3BF8>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
直接調用父類的的__init__(self)
方法,把__init__(self)
當作普通函數使用,傳入對象與繼承的屬性
使用super函數,super是一個特殊的類,在子類中調用super()會獲得一個特殊的對象,經過「.」 指向父類的名稱空間,將自己傳入__init__(self)
函數當中的一個參數
注意:兩種方式不要混合使用。
class OldboyPeople: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex # 方式一: # 直接調用父類的__init__(self)函數 class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level): OldboyPeople.__init__(self,name,age,sex) self.level = level class OldboyStudent(OldboyPeople): def __init__(self,name,age,sex,course): OldboyPeople.__init__(self, name, age, sex) self.course = course stu1 = OldboyStudent("qinyj",18,"man","python") tea1 = OldboyTeacher("tank",18,"man","10") print(tea1.name,tea1.level) print(stu1.name,stu1.course) # 方式二: # 使用super()函數 class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level): super().__init__(name,age,sex) self.level = level class OldboyStudent(OldboyPeople): def __init__(self,name,age,sex,course): super().__init__(name, age, sex) self.course = course stu1 = OldboyStudent("qinyj",18,"man","python") tea1 = OldboyTeacher("tank",18,"man","10") print(tea1.name,tea1.level) print(stu1.name,stu1.course)
繼承了 object 類的是新式類,沒有繼承的是經典類
新式類:python3中都是新式類,在python3中默認繼承object類
經典類:python2中凡是沒有繼承object類的都是經典類
mro函數屬於object類,在多繼承狀況下,用來查看當前類的繼承順序的
class A: x = 2 pass class B: x = 3 pass class C(A,B): x = 1 pass # mro函數 print(C.mro()) # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] # 繼承順序: # 先在本身類中找--》A--》B--》object c = C() print(c.x)
在多繼承的狀況下造成的鑽石繼承
針對於新式類和經典類而言:
經典類:深度優先
新式類:廣度優先
驗證:
# coding=utf-8 ### 新式類繼承 # 繼承順序:F-D->B->E->->C->A->object-->若沒有報錯 class A(object): def test(self): print("from A") pass class B(A): # def test(self): # print("from B") pass class C(A): # def test(self): # print("from C") pass class D(B): # def test(self): # print("from D") pass class E(C): # def test(self): # print("from E") pass class F(D,E): # def test(self): # print("from F") pass f = F() f.test() ### 經典類繼承 # 繼承順序:F->D->B->A->E->C-->若沒有報錯 class A: # def test(self): # print("from A") pass class B(A): # def test(self): # print("from B") pass class C(A): # def test(self): # print("from C") pass class D(B): # def test(self): # print("from D") pass class E(C): # def test(self): # print("from E") pass class F(D,E): # def test(self): # print("from F") pass f = F() f.test()
import json from datetime import datetime,date print(json.JSONEncoder) ''' json 支持的python數據類型 +-------------------+---------------+ | Python | JSON | +===================+===============+ | dict | object | +-------------------+---------------+ | list, tuple | array | +-------------------+---------------+ | str | string | +-------------------+---------------+ | int, float | number | +-------------------+---------------+ | True | true | +-------------------+---------------+ | False | false | +-------------------+---------------+ | None | null | +-------------------+---------------+ ''' print(datetime.today()) print(date.today()) # 開發者的角度來講,咱們想要把date.today() 或者datetime.today() 當成json 的value值保存爲json文件 # 但json數據類型只支持字符串,那麼咱們能夠這麼作,將執行結果強轉爲str dic = { "name":"qinyj", "today":str(date.today()) } print(json.dumps(dic)) # {"name": "qinyj", "today": "2019-10-10"} # 咱們從源碼角度來看,有可能之後會本身修改源碼 class MyJson(json.JSONEncoder): # 子類從新派生出來default功能,優先用子類的 def default(self, o): if isinstance(o,date): return o.strftime("%Y-%m-%d %X") else: # 不知足條件仍是繼承父類的default方法的功能 return super().default(self,o) dic = { "name":"qinyj", "today":date.today() } # isinstance() :判斷一個對象是不是一個已知的類型 print(isinstance(dic,date)) print(isinstance(dic.get("today"),date)) print(json.dumps(dic,cls=MyJson)) # 默認cls=None,默認指向的是原json的JSONEncoder # {"name": "qinyj", "today": "2019-10-10 00:00:00"}
1.什麼是繼承? 繼承指的是新建類的方法, 新建的類稱之爲子類或者派生類,子類繼承的類叫作父類,也稱之爲基類或超類. 繼承的特徵: 子類能夠繼承父類的屬性(特徵與技能), 而且能夠派生出本身的屬性(特徵與技能). 2.繼承的目的: 繼承的目的是爲了減小代碼冗餘(減小重複代碼). 3.什麼是抽象? 抽象指的是抽取類似的部分,稱之爲抽象. 4.繼承的關係: 對象是特徵與技能的結合體. 類是一系列對象相同的特徵與技能的結合體. 繼承是一系列類相同的特徵與技能的結合體. 5.在繼承背景下,對象屬性的查找順序: 1.對象查找屬性會先從對象的名稱空間中查找. 2.若對象沒有,則會去類裏面找. 3.若當前類是子類,而且沒有對象找的屬性,會去父類中查找 6.什麼是派生? 派生指的是子類繼承父類的屬性,而且派生出新的屬性.(*****) 子類派生出新的屬性,若與父類的屬性相同,則以子類的爲準. 繼承是誰與誰的關係, 指的是類與類的關係,子類與父類是從屬關係. 7.子類派生出新的屬性,並重用父類的屬性: - 直接經過 父類.(調用)__init__,把__init__當作普通函數使用,傳入對象與繼承的屬性. - super是一個特殊的類,在子類中調用super()會獲得一個特殊的對象, 8.什麼經典類與新式類: 繼承object的類都稱之爲新式類. 在python2中,凡是沒有繼承object的類都是經典類. 9.在多繼承的狀況下造成的鑽石繼承 (繼承順序) - 經典類: 深度優先 - 新式類: 廣度優先