21.面向物件三大特徵 21.繼承與抽象 屬性的查詢順序 派生與覆蓋 子類訪問父類 初始化方法 必須呼叫super 組合 多繼承
阿新 • • 發佈:2022-03-25
OOP三大特徵
1.OOP 面向物件 三大特徵 封裝 繼承 多型 1.繼承 什麼是繼承 繼承是一種關係,描述兩個物件之間,什麼是什麼的關係 例如麥兜,佩奇,豬剛鬣 都是豬啊, 在程式中,繼承描述的是類和類之間的關係 例如a繼承了b, a就能直接使用b已經存在的方法和屬性 a稱之為子類,b稱之為父類,也稱之為基類 2.為什麼要使用繼承 繼承的一方可以直接使用被繼承一方已經有的東西 其目的是為了重用已經有的程式碼,提高重用性 ## 如何使用繼承 語法: class 類名稱(父類的名稱): 類的內容 #在python中 一個子類可以同時繼承多個父類OOP三大特徵2.抽象 不具體 不清晰 很模糊 看不懂 將多個子類中相同的部分,進行抽取,形成新的類,這個過程也稱為 抽象的 過程 正確的使用繼承 1.先抽象再繼承 2.繼承一個已經現存的類,擴充套件或是修改原始的功能 3.屬性的查詢順序 物件自己的 - > 所在類中 -> 找父類 - >父類的父類 ->Object 4.派生 與 覆蓋 派生: 當一個子類中出現與父類中不同內容時,這個子類就稱為派生類 通常子類都會寫一些新的程式碼,不可能和父類完全一樣 , 既通常都是派生類, 所以派生類指的就是子類 覆蓋 也稱之為重寫 overriders 當子類出現了與父類名稱完全一致的屬性或是方法6.子類訪問父類的內容 語法: 方式1: super(當前類名稱,self).你要調的父類的屬性或方法 方式2: super().你要調的父類的屬性或方法 方式3: 類名稱.你要調的父類的屬性或方法(self) #方式3與繼承無關 #### 強調在強調: 當你繼承一個現有的類,並且你覆蓋了父類的init方法時,必須在初始化方法的第一行呼叫父類的初始化方法,並傳入父類所需的引數 8.組合 也是一種關係,描述兩個物件之間 是什麼有什麼的關係 例如,學生有手機 ,遊戲中角色擁有某些裝備 將一個物件作為另一個物件的屬性,(既什麼有什麼) 組合的目的:也是為了重用現有程式碼 什麼時候使用繼承:分析兩個類的關係,到底是不是:什麼是什麼的關係 什麼時候使用組合:如果兩個類之間 沒有太大的關係,完全不屬於同類 另外組合相比繼承,耦合度更低了 瞭解知識點## 菱形繼承 首先明確python支援多繼承 ##### 補充:新式類與經典類 python3中任何類都是直接或間接繼承了Object 新式類,任何顯式或隱式地繼承自object的類就稱之為新式類, python3中全都是新式類 經典類,既不是Object的子類 ,僅在python2中出現 當出現了菱形繼承時,新式類,先深度,當遇到了共同父類時就廣度 新式類,就是深度優先 # 小結: 1.繼承是什麼 2.為什麼用繼承 3.語法 4.先抽象在繼承 6.派生 7.覆蓋 8.子類訪問父類的屬性或方法 super ().名字 如果你繼承一個已有的類,並且你覆蓋了init 一定要先呼叫父類的init 9.繼承的原理,mro列表 10,新式類與經典類 11.菱形繼承 瞭解 12,屬性的查詢順序
class Base: desc = "這是一個基類" def show_info(self): print(self.desc) def make_money(self): print("明天立馬找到工作") # 指定父類 位 Base class SubClass(Base): pass #即使類中什麼都沒有也可以使用父類中已有的內容 obj = SubClass() obj.make_money() print(obj.desc)1.繼承的基本語法.py
# 抽取老師和學生中相同的部分形成person類 class Person: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def say_hi(self): print("name:%s,age:%s,gender:%s" % (self.name,self.age,self.gender)) class Teacher(Person): def teacher(self): print("老師教學生,寫程式碼....") t1 = Teacher('jack',20,'male') t1.say_hi() class Student(Person): pass stu1 = Student('rose',18,'female') stu1.say_hi()2.繼承與抽象.py
class A: text = "haha" class B(A): text = "heihei" pass b = B() b.text = "xixi" print(b.text)3.屬性查詢順序.py
class Person: def say_hi(self): print("hello") class Student(Person): def say_hi(self): print("hello world!") stu = Student() stu.say_hi()4.派生與覆蓋.py
""" 需求 實現一個能夠限制元素型別的列表類 """ class MyList(list): def __init__(self,element_type): super().__init__() # # 呼叫父類的初始化方法 來完成基本的初始化 self.element_type = element_type def append(self, object): """ :param object: 是要儲存的元素 :return: 沒有 """ if type(object) == self.element_type: # 我們需要在這裡訪問父類的append函式來完成真正的儲存操作 super(MyList,self).append(object) else: print("sorry sir ,you element type not is %s" % self.element_type) # 建立是指定要儲存的元素型別 m = MyList(int) # 當你有需求,是需要在建立物件時 乾點什麼事兒 那就該想到初始化方法 m.append(1) print(m[0]) m.append("12223")5.實現一個可以限制元素型別的列表.py
class Parent: text = 'abc' def say_something(self): print("anything") class Sub(Parent): def show_info(self): print(super(Sub,self).text,1) print(super(Sub,self).say_something()) # 訪問方式2 py3的新語法 最常用的方式 print(super().text,2) super().say_something() # 方式3 直接指定類名呼叫 print(Parent.text) Parent.say_something(self) sub = Sub() sub.show_info()6.子類訪問父類的內容.py
# class Person: # def __init__(self,name,gender,age): # self.name = name # self.gender = gender # self.age = age # # def say_hi(self): # print("name:%s ,gender:%s,age:%s" % (self.name,self.gender,self.age)) # # class Student(Person): # def __init__(self,name,gender,age,number): # super().__init__(name,gender,age) # self.number = number # def say_hi(self): # super().say_hi() # print("number:%s" % self.number) # # # stu = Student("rose","mael",20,"old01") # stu.say_hi() # 為什麼要在初始化方法中呼叫 父類的初始化方法 class Person: def __init__(self,name,gender,age,*args): self.name = name self.gender = gender self.age = age self.aa() def aa(self): print("aa run") def say_hi(self): print("name:%s ,gender:%s,age:%s" % (self.name,self.gender,self.age)) class Student(Person): def __init__(self,name,gender,age,number): super().__init__(name,gender,age) self.number= number def say_hi(self): super().say_hi() print("numnber:%s" % self.number) stu = Student("rose", "mael", 20, "old01") stu.say_hi()7.初始化方法必須呼叫super.py
class Phone: def __init__(self,price,kind,color): self.price = price self.kind = kind self.color = color def call(self): print("正在呼叫XXXX;") def send_message(self): print("正在傳送簡訊....") class Student: def __init__(self,name,gender,phone): self.name = name self.gender = gender self.phone = phone def show_info(self): print("name:%s gender:%s" % (self.name,self.gender)) phone = Phone(1000,"apple","red") stu1 = Student("rose","male",phone) stu1.phone.call()8.組合.py
# # coding:utf-8 # class A: # pass # # class B: # pass # # class C: # pass # # class Test(A,B,C): # pass # # print(Test.mro()) """ [<class '__main__.Test'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>] """ # class A(object): # pass # # print(A.mro()) # [<class '__main__.A'>, <class 'object'>] # # print(A.__dict__) """ {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None} """ # 菱形繼承 # class A: # j = 1 # pass # # class B: # # j = 2 # pass # # class C(A): # # j = 3 # pass # # class D(A): # j = 4 # pass # # class E(B,C,D): # # j = 5 # pass # # d = E() # print(d.j) class B: # num = 2 pass class C: # num = 3 pass class E(B): # num = 5 pass class F(C): # num = 6 pass class G(C): num = 7 pass class H(E,F,G): # num = 8 pass print(H.num) # print(H.mro()) #[H,E,B,F,G,C,object]9.多繼承.py
抽象
菱形繼承的查詢順序