面向物件三大特性之一:繼承
目錄
-
動態方法與靜態方法
-
面向物件的三大特性之一:繼承
-
派生(前瞻)
內容
一.動態方法與靜態方法
動態方法
1.繫結給物件的方法
class Stdent:
school = '清華大學' def run(self): print(self)
類呼叫繫結給物件的方法:有幾個引數就需要傳幾個引數
Student.run(123) # 123
物件呼叫繫結給物件的方法:會自動將物件當作第一個引數傳入
obj = Student()
obj.run() # <__main__.Student object at 0x0000017844C11190>
2.繫結給類的方法
class Student: @classmethod def eat(cls): print(cls)
類呼叫繫結給類的方法:會自動將類當作第一個引數傳入
print(Student) # <class '__main__.Student'> Student.eat() # <class '__main__.Student'>
物件呼叫繫結給類的方法:也不需要傳參 會講產生該物件的類自動當作第一個引數傳入
obj = Student() obj.eat() # <class '__main__.Student'>
靜態方法
就是普普通通的函式:無論誰來呼叫 都必須傳入固定的引數個數
class Student: @staticmethod def speak(a): print(a)
類呼叫靜態方法:自己傳值
Student.speak(123) # 123
物件呼叫靜態方法:自己傳值
obj = Student() obj.speak(321) # 321
二.面向物件的三大特徵之一:繼承
面向物件三大特徵:繼承、封裝、多型
1.繼承的含義:
現實生活中繼承是用來描述人與人之間資源的從屬關係
eg:兒子繼承父親 那麼就可以擁有父親的一切
面向物件中繼承則是用來描述類與類之間資料的從屬關係
2.繼承的目的:
現實生活中通過繼承可以快速的積累財富少奮鬥N多年 並且可以多繼承
eg:可以認多個爹 磅多個富婆
面向物件中通過繼承可以減少程式碼冗餘 提升開發效率 同樣也支援多繼承
eg:類A可以繼承多個類同時擁有多個類裡面的程式碼使用權
3.繼承的基本使用:
class A(B): pass class A(B,C,D): pass
A:繼承別人的類(子類或者派生類) B:被繼承的類(父類或者基類)
一個類可以同時繼承多個父類
4.繼承的本質:
抽象:由下往上抽取相同特徵 繼承:由上往下直接白嫖資源
物件:資料與功能的結合體
類:多個物件相同資料和功能的結合體
父類:多個類相同資料和功能的結合體
class Person: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender class Teacher(Person): def teach(self): print(f'{self.name}老師正在講課') class Student(Person): def study(self): print(f'{self.name}學生正在學習') stu = Student('jason', 18, 'male') stu.study() # Jason學生正在學習
5.名字的查詢順序:
名字的查詢順序永遠都是 先從當前物件自身開始查詢
1.不繼承的情況下:物件 >>> 類
名字的查詢順序:先從物件自己的名稱空間中查詢 沒有則去類裡面的名稱空間查詢
ps:注意設定值的情況下是在自身的名稱空間中新增或者修改資料
2.單繼承的情況下:物件 >>> 類 >>> 父類
名字的查詢順序是:先從物件自己的名稱空間中查詢 沒有擇取產生物件的類中查詢 如果還沒有並且類有父類則去父類中查詢 以此往復下去
class A: def f1(self): print('from A.f1') def f2(self): print('from A.f2') self.f1() '''以後看到self點東西 一定要問自己self是誰''' class MyClass(A): def f1(self): print('from MyClass.f1') obj = MyClass() obj.f2() # 執行的方法分別是A裡面的f2和MyClass裡面的f1
3.多繼承的情況下:(瞭解)
在python2中存在經典類與新式類 在python3中只有新式類
區分的關鍵在於是否繼承了一個預設的object類
新式類:直接或者間接繼承了object或者其子類的類
經典類:不繼承任何的類
class A: pass # print A.__bases__ # 空的 # print(A.__bases__) # (<class 'object'>,)
有時候我們在定義類的時候會習慣性的寫:(為了相容python2和python3)
class MyClass(object): pass
強度:研究菱形和非菱形問題object不參與圖形構建
非菱形繼承的情況下:父類中名字的查詢順序就是按照繼承時從左往右依次查詢 “深度優先”
菱形繼承的情況下:父類中名字的查詢順序就是按照繼承時從左往右依次查詢 “廣度優先”
三.派生
如果自己寫的子類需要使用父類的方法 並且還需要基於該方法做擴充套件
這樣的子類我們稱之為派生類(本質還是子類)
那麼可以使用super關鍵字來實現
class Person: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender class Teacher(Person): def __init__(self,name,age,gender,level,salary): # 用了Person類裡面的__init__方法之後 # super(Teacher,self).__init__(name,age,gender) # 子類呼叫父類的方法 完整語法 super().__init__(name,age,gender) # 子類呼叫父類的方法 精簡語法 # 自己還要新增一個額外的東西 self.level = level self.salary = salary class Student(Person): def __init__(self,name,age,gender,stu_id,class_id): # 用了Person類裡面的__init__方法之後 super().__init__(name, age, gender) # 自己還要新增一個額外的東西 self.stu_id = stu_id self.class_id = class_id
列印結果為:
t1 = Teacher('jason',18,'male','滿級',3.1) s1 = Student('kevin',28,'female',1302010201,2) print(t1.__dict__) # {'name': 'jason', 'age': 18, 'gender': 'male', 'level': '滿級', 'salary': 3.1} print(s1.__dict__) # {'name': 'kevin', 'age': 28, 'gender': 'female', 'stu_id': 1302010201, 'class_id': 2}
派生功能前瞻
class MyClass(list): def append(self,args): if args == 123: print('數字123不能追加') return super(MyClass, self).append(args) obj1 = MyClass() obj1.append(333) obj1.append(222) obj1.append(123) print(obj1) # [333, 222]