面向對象之繼承
一.繼承基礎
1.什麽是繼承?
繼承指的是一種關系,它必須存在兩個對象,才會發生繼承這件事。在程序中,繼承指的是類與類之間的關系。被繼承的稱為父,繼承的稱為子。
2.為什麽要使用繼承?
在程序中,通過繼承可以直接使用父類已有的代碼,從而簡化代碼。
3.如何使用繼承?
語法:在子類中,類名後面加括號,括號裏寫上父類的名稱即可,可以是多個,用逗號分隔開。
子類可以使用父類中的屬性,也可以使用父類中的函數。
# class Father: # pass # # # class GanDie: # pass # # # 在子類中 類名後面加上括號,些上父類的名稱即可, # # 在python中一個子類可以有多個父類,多個父類在括號中用逗號隔開,,這一點在其他語言中是不支持的繼承的使用# class Son(Father,GanDie): # pass class Parent: year = 2018 def coding(self): print("正在編程........") class Sub(Parent): pass print(Parent.year) print(Sub.year) # Sub.coding() s = Sub() print(s.year) # 子類可以使用父類中的屬性 s.coding() # 子類也可以父類中的函數
子類繼承父類之後會出現一個問題,就是子類可能會繼承到一些不應該有的屬性,這就需要用到抽象的概念。
抽象指的是抽取多個類中相同的部分形成另一個類。這樣就可以避免繼承到一些不應該有的內容,在抽取的過程中,也可能會產生一些跟業務需求無關的類,但是並不影響。
class Person: def __init__(self ,name ,age ,sex): self.name = name self.age = age self.sex = sex def eat(self): print("正在吃飯....") def study(self): print("正在學習....")抽象class Teacher(Person): def teaching(self): print("老師正在上課......") t1 = Teacher("blex" ,30 ,"woman") t1.eat() t1.study() class Student(Person): pass stu1 = Student("張三" ,20 ,"man") stu1.eat() stu1.study()
二.派生與覆蓋
1.什麽是派生?
派生指的是子類繼承某個父類,並且子類擁有自己獨特的屬性或者技能。只要子類中出現了任何新的內容,它就是一個派生類。
class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def sayHI(self): print("hello 我是%s 今年%s歲 性別:%s" % (self.name,self.age,self.sex)) # Test不能稱為派生類 , 因為沒與任何獨特的內容與父類完全一致 class Test(Person): pass # 派生類屬於子類嗎? 派生類一定是某個子類 # Student類就成為 Person類的派生類 class Student(Person): def __init__(self,name,age,sex,number): self.name = name self.age = age self.sex = sex self.number = number # 上課 def up_class(self): print("%s 正在上課.....")派生
2.什麽是覆蓋?
在子類中,如果存在與父類相同的屬性名稱時,優先使用子類中的屬性,這種行為稱之為覆蓋。
三.子類訪問父類的方法
簡單的來說有兩種方法:
1.指名道姓的訪問(父類名點語法)
2.用super()函數訪問(super()點語法)。該函數一定是用在存在繼承關系的子類中的。在python2中用法:super(子類名,self)點語法。
class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex print(self) def sayHI(self): print("hello 我是%s 今年%s歲 性別:%s" % (self.name,self.age,self.sex)) class Student(Person): def __init__(self,name,age,sex,number): # self.name = name # self.age = age # self.sex = sex #上述代碼與父類中完全相同 Person.__init__(self,name,age,sex) self.number = number # 上課 def up_class(self): print("%s 正在上課.....") def sayHI(self): # print("hello 我是%s 今年%s歲 性別:%s" % (self.name,self.age,self.sex)) # 訪問父類中的方法來簡化代碼 # 指名道姓 Person.sayHI(self) print("學號:",self.number) stu1 = Student("阿三",20,"woman","9527") # print(stu1) # print(stu1.name,stu1.age,stu1.sex) stu1.sayHI()方法一
class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex print(self) def sayHI(self): print("hello 我是%s 今年%s歲 性別:%s" % (self.name,self.age,self.sex)) class Student(Person): def __init__(self,name,age,sex,number): # self.name = name # self.age = age # self.sex = sex # 子類中重用父類種方法的方式2 # super() # 表示創建一個特殊的對象 用於調用父類的方法 # super().__init__(name,age,sex) # 了解:在python2中 super的使用方式有所不同 需要傳入當前類,當前對象 super(Student,self).__init__(name,age,sex) self.number = number # 上課 def up_class(self): print("%s 正在上課.....") stu1 = Student("阿三",20,"woman","9527") print(stu1) print(stu1.name,stu1.age,stu1.sex)方法二
四.繼承的屬性查找順序
查找順序:對象---》類---》父類---》父類的父類......
優先查找對象,如果不存在,則找類,如果類中不存在,則會沿著繼承關系一直找到最頂層的父類。方法的查找順序也是一樣。
class S: age = 17 def f1(self): print("S f1") class A(S): # age = 18 # def f1(self): # print("A f1") pass class B(A): # age = 19 # def f1(self): # print("B f1") pass b = B() # b.age = 20 print(b.age) print(b.__dict__) print(B.__dict__) print(A.__dict__) # 對象 -> 類 ->父類 ->父類的父類..... # 優先找對象 如歌對象沒有 則找類,如果類沒有,會沿著繼承關系一直找到最頂層的父類 # 無論是屬性還是方法 查找順序是一樣的 b2 = B() b2.f1()基本查找順序
如果繼承關系為菱形結構,那麽屬性的查找方式有兩種,分別是:深度優先和廣度優先
# class E: # a = 5 # # class A(E): # a = 4 # pass # # class B: # a = 3 # pass # # class C: # a = 2 # pass # # class D(A,B,C): # # a = 1 # pass # # d1 = D() # # d1.a = 10 # print(d1.a) # 1.按照繼承的順序 先繼承誰就先找誰 class S: a = 100 class A(S): # a = 1 pass class B(S): # a = 2 pass class C(S): # a = 3 pass class D(A): # a = 4 pass class E(B): # a = 5 pass class F(C): # a = 6 pass class G(D,E,F): pass g1 = G() print(g1.a) print(G.mro()) """ s a,b,c d,e,f g """菱形繼承的屬性查找
五.經典類與新式類
新式類:所有直接或間接繼承object的類都是新式類。object稱之為根類,即所有的類都源自於object類。(創建對象時,需要申請內存空間,創建新的名稱空間,將對象的屬性放入名稱空間,這一些了復雜的基礎操作,都有object來完成。簡單地說:object提供了一些常用的基礎操作。)
在python3中默認所有類都是新式類,在python2中默認是經典類(不會自動繼承object)。
__bases__用於查看父類,mro()方法是一個列表,存放的是屬性的查找順序。
"super訪問父類內容時 按照mro列表屬性查找" class S: def f1(self): print("s f1") class A(S): pass class B(S): def f1(self): print("b f1") pass class C(A,B): def f2(self): print("c f2") super().f1() print(C.mro()) c1 = C() c1.f2() class S: pass class Student(S): pass # __bases__用於查看父類 print(Student.__bases__) # 顯示屬性的查找順序列表,屬性查找屬性就是按照該列表來查找的 print(Student.mro())View Code
面向對象之繼承