繼承是一種新建類的方式,新建的類稱爲子類或者派生類,被繼承的類稱爲父類、基類或者超類python
在python中,一個子類能夠繼承多個父類,其餘語言中,一個子類只能繼承一個父類json
減小類與類之間的代碼冗餘學習
子類能夠繼承父類的全部屬性,所以繼承能夠解決類與類之間的代碼冗餘問題code
子類能夠經過 子類.__ bases__ 查看父類對象
肯定誰是子類blog
肯定誰是父類,先抽象再繼承繼承
抽象總結出對象之間類似的部分,再總結出類字符串
抽象總結類之間類似的部分,再總結出父類it
# 解決代碼冗餘 # 父類 class People: country = 'China' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex # 子類1 class Student(People): def learn(self): return '學習技能' # 子類2 class Teacher(People): def teach(self): return '教書技能' # 子類能夠繼承父類的屬性 stu_obj = Student('shen', 18, 'male') print(stu_obj.name, stu_obj.age, stu_obj.sex, stu_obj.country, stu_obj.learn()) # shen 18 male China 學習技能 tea_obj = Teacher('wang', 24, 'female') print(tea_obj.name, tea_obj.age, tea_obj.sex, tea_obj.country, tea_obj.teach()) # wang 24 female China 教書技能
程序的執行是從上往下執行的,父類必須定義在子類上面class
在繼承的背景下,對象的屬性查找順序:
python3中只有新式類,廣度優先查找:繼承多個父類時一直到繼承object的類(根父類)不會從中找會回頭找,第二個繼承的父類。。。
python2中有經典類和新式類,深度優先查找:一直找到繼承object的類(根父類)從中找不到纔會找繼承的第二個父類。。。
# 父類 class Foo: x = 10 #子類 class Goo(Foo): x = 20 pass obj_goo = Goo() # 注意此處的x是經過對象來添加屬性,是給對象添加屬性,不是修改子類的屬性 obj_goo.x = 30 print(obj_goo.x)
指的是子類繼承父類的屬性與方法,而且派生出本身獨有的屬性與方法
若子類中的方法與父類的相同,優先用子類的
# 父類 class Foo: def f1(self): print('from Foof1...') def f2(self): print('from Foof2...') # 注意此處查找的f1應該先優先從子類找,最後從父類找 self.f1() # 子類 class Goo(Foo): def f1(self): print('from Goof1...') goo_obj = Goo() goo_obj.f2() # from Foof2... # from Goof1...
方式一:
直接引用父類的__ init__(self)爲其傳參,並添加子類的屬性
方式二:
經過super來指向父類的屬性,用super().init()爲其傳參添加子類的屬性
super()是一個特殊類,調用super獲得一個對象,該對象指向父類的名稱空間
注意:使用哪種方式均可以,可是不要混用
# 需求:學生有女友屬性,老師有薪資屬性 # 父類 class Foo: country = 'China' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex # 子類 class Student(Foo): def __init__(self, name, age, sex, gril): # 方式一:直接引用父類的,須要傳入self和其餘參數 Foo.__init__(self, name, age, sex) self.gril = gril class Teacher(Foo): def __init__(self, name, age, sex, sal): # 方式二:對象自己當作self傳入,不用super不要傳入self,傳入其餘參數 super().__init__(name, age, sex) self.sal = sal stu_obj = Student('shen', 18, 'male', 'gril') print(stu_obj.country, stu_obj.name, stu_obj.age, stu_obj.sex, stu_obj.gril) # China shen 18 male gril tea_obj = Teacher('wang', 24, 'female', 200000) print(tea_obj.country, tea_obj.name, tea_obj.age, tea_obj.sex, tea_obj.sal) # China wang 24 female 200000
新式類:
1. 凡是繼承了object的類或子孫類都是新式類
2.在python3中全部的類都默認繼承了object
經典類:
1. 在python2中才會有經典類與新式類之分
2.在python2中,凡是沒有繼承object的類,都是經典類
# python3中 class Foo: # 默認繼承了object(Foo(object):) x = 1 pass class Goo(Foo): pass print(Foo.__dict__) print(Goo.__dict__) # {'__module__': '__main__', 'x': 1, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None} # {'__module__': '__main__', '__doc__': None}
python3中提供了一個查找新式類查找順序的內置方法,經過類調用mro()獲得的返回結果是一個繼承序列
super的繼承順序嚴格按照mro()繼承序列,會基於當前位置按照mro序列順序繼續日後查找
class Foo1: def res(self): print('res from Foo1') # super會按照mro中序列基於當前位置繼續日後查找 super().res() class Foo2: def res(self): print('res from Foo2') class C(Foo1, Foo2): pass obj_c = C() print(C.mro()) # [<class '__main__.C'>, <class '__main__.Foo1'>, <class '__main__.Foo2'>, <class 'object'>] obj_c.res() #res from Foo1 # res from Foo2
多繼承狀況下的菱形繼承
mro的查找順序:
新式類:廣度優先
經典類:深度優先
新式類的廣度優先:
# 新式類: 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-->D-->B-->E-->C-->A-->object print(F.mro()) #[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] obj = F() obj.test()
經典類的深度繼承:
json模塊正常沒法存入類,轉成json數據格式的,先若是須要存入一個類的數據則有兩種方式
import json from datetime import datetime dic = {'time': datetime.now()} print(type(datetime.now())) # <class 'datetime.datetime'> # datetime.now()是一個類<class 'datetime.datetime'>正常沒法轉換存成json數據格式的 json.dumps(dic) # TypeError: Object of type datetime is not JSON serializable
方法一:將類轉換成字符串存入
import json from datetime import datetime # 方法一:轉換成字符串存入 dic = {'time': str(datetime.now())} res = json.dumps(dic) print(res) # {"time": "2019-11-27 14:38:01.079162"}
方法二:繼承json模塊派生出新功能來存取
import json from datetime import datetime # 方法二:繼承json模塊派生出新功能來存取 class MyJson(json.JSONEncoder): def default(self, o): # isinstance: 判斷一個對象是不是一個類的實例 if isinstance(o, datetime): return datetime.strftime(o, '%Y-%m-%d %X') else: return super().default(self, o) dic = {'time': datetime.now()} # cls=自定義的類 res = json.dumps(dic, cls=MyJson) print(res) # {"time": "2019-11-27 14:38:01"}