1. 程式人生 > 其它 >面向物件三大特性之一:繼承

面向物件三大特性之一:繼承

目錄

  • 動態方法與靜態方法

  • 面向物件的三大特性之一:繼承

  • 派生(前瞻)

     

     

     

內容

一.動態方法與靜態方法

動態方法

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]