第九章、物件導向

xmd_bmx發表於2020-10-31

第九章、物件導向

一、類的定義

  1. 格式:

    • # classnam類名
      class classname(object):
          """
          程式碼段
          """
          pass
      
  2. 呼叫方式:例項化

    • class Student():
          name = ""
          age = 0
          def print_file():
              pass
      # 例項化
      student = Student()
      # 呼叫類下面的方法
      student.print_file()
      # 執行會報錯
      # 解決方法
      在方法中間寫入self
      class Student():
          name = ""
          age = 0
          def print_file(self):
              print("name:"+name)
              print("age:"+str(age))
      student = Student()
      student.print_file()
      # 執行結果
      還是報錯
      繼續修改
      class Student():
          name = ""
          age = 0
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      student = Student()
      student.print_file()
      # 執行結果
      name:
      age:0
      
    • 類的最基本的作用就是封裝程式碼

    • 類中的方法在書寫時引數一定要加self

二、類與物件

  1. 在別的模組中引用類

    • from c1 import Student
      student = Student()
      student.print_file()
      # 結果:
      name:
      age:0
      
  2. 方法和函式的區別

    • 沒有一個絕對的區別
  3. 定義在類中的變數不能叫變數,應該是資料成員,定義在類外面的資料才叫變數

  4. 類:

    1. 什麼是類?
      • 類就是將資料和對這些資料的操作封裝在了一起
      • 類是一個事物的抽象,並不是具體的
      • 資料成員刻畫特徵
      • 方法刻畫行為,行為需要找對主體
      • 類就像一個模板一樣,通過類可以產生很多個物件
  5. 物件:

    1. 什麼是物件
      • 物件則是表示一個具體的事物,就是將類例項化
      • 當類被例項化之後就會變成例項物件
      • 只有給例項化後的類傳入特徵值,物件才能有對應特徵
  6. 例項化:

    • class Student():
          name = ""
          age = 0
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student()
      student2 = Student()
      student3 = Student()
      # 建立3個不同的例項化物件,特徵是相同的,但是實際上又是獨立開的不同的物件
      

三、建構函式

  1. 如果要在類中傳入特徵值,需要定義一個特殊的函式__init__()

  2. class Student():
        name = ""
        age = 0
        def __init__(self):
            # 建構函式
            print("student")
            pass
        def print_file(self):
            print("name:"+self.name)
            print("age:"+str(self.age))
    
    student1 = Student()
    student1.__init__()
    # 結果:
    student
    student # 出現了兩次列印
    
  3. 出現兩次的原因是因為當我們例項化類的話,建構函式會被自動呼叫,也可以主動呼叫建構函式

  4. 建構函式返回值是None,不能返回別的值

  5. 建構函式的作用

    1. 可以讓模板生成不同的物件

    2. 在建構函式中建立了形參後,就必須在例項化類中寫入實參,不寫的話會報錯

      class Student():
          # name = ""
          # age = 0
          def __init__(self,name,age):
              # 建構函式
              print("student")
              pass
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student()
      student1.__init__()
      # 執行結果:
      報錯
      class Student():
          # name = ""
          # age = 0
          def __init__(self,name,age):
              # 建構函式
              print("student")
              pass
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      student1 = Student('劉小剛', 2)
      student1.print_file()
      # 執行結果:
      student
      空 # 並沒有修改成功
      
      class Student():
          name = ""
          age = 0
          def __init__(self,name,age):
              # 建構函式
              # 初始化物件的特徵
              self.name = name
              self.age = age
              print("student")
              pass
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student('劉小剛', 2)
      student1.print_file()
      # 執行結果:
      student
      name:劉小剛
      age:2
      

四、類變數1和例項變數2

  1. 類變數:是定義在類中的變數

    • class Student():
          # 類變數
          name = ""
          age = 0
          def __init__(self,name,age):
              # 建構函式
              # 初始化物件的特徵
              # 例項變數
              self.name = name
              self.age = age
              print("student")
      
    • 類變數的意義:類變數和特徵變數是無關的,也就是和成員屬性是無關的

  2. 例項變數:是定義在__init__()中,例項變數的定義方式是self.變數名

    • class Student():
          # 類變數
          name = ""
          age = 0
          def __init__(self,name,age):
              # 例項變數
              self.name = name
              self.age = age
              print("student")
      
  3. 例項變數和類變數的區別

    • class Student():
          name = "qiyue"
          age = 0
          def __init__(self,name,age):
              # 建構函式
              # 初始化物件的特徵
              self.name = name
              self.age = age
      
      student1 = Student('劉小剛', 2)
      print(student1.name)
      print(Student.name)
      # 結果:
      劉小剛
      qiyue
      
    • 物件的.name和例項物件的.name是不同的

  4. __dict__3

    • class Student():
          name = "qiyue"
          age = 0
          def __init__(self,name,age):
              # 建構函式
              # 初始化物件的特徵
              name = name
              age = age
      
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student('劉小剛', 2)
      print(student1.name)
      # 結果:
      qiyue
      
    • 為何沒有修改該變數

    • class Student():
          name = "qiyue"
          age = 0
          def __init__(self,name,age):
              # 建構函式
              # 初始化物件的特徵
              self.name = name
              age = age
      
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student('劉小剛', 2)
      
      print(student1.__dict__)
      # 結果
      只有一個例項變數,{'name': '劉小剛'}
      
    • 為什麼例項變數不存在,還能列印出qiyue

      • 這和變數的尋找機制有關,當在特徵變數中找不到值的時候,他就會到類中尋找,若在類中也找不到,那麼就會向上(父類)中繼續尋找
  5. self

    • 特性:如果要在類中定義一個例項方法,那麼第一個引數需要寫self,而在我們呼叫這個方法發時候是不需要傳入這個引數的,self是預設傳入的
    • self可以不叫self,可以寫this或別的,但是python建議我們用self,顯勝與隱
    • self的意義:呼叫這個方法的例項物件,換句話說就是self代表的是呼叫的物件,而不是類
  6. 例項方法:

    • 是和物件相關聯的方法

    • 例項方法中訪問類變數

    • 在例項方法中無法訪問類變數。

      • class Student():
            name1 = "qiyue"
            age1 = 0
            def __init__(self, name, age):
                # 建構函式
                # 初始化物件的特徵
                self.name = name
                self.age = age
                print(name1)
                print(age1)
                
        student1 = Student('劉小剛', 2)
        # 結果
        報錯
        
    • 通過類名直接呼叫類變數、或者通過self.__class__.類變數名

      • class Student():
            name1 = "qiyue"
            age1 = 0
            def __init__(self, name, age):
                # 建構函式
                # 初始化物件的特徵
                self.name = name
                self.age = age
                # print(Student.name1)
                print(self.__class__.name1)
                # print(Student.age1)
                print(self.__class__.age1)
        
        student1 = Student('劉小剛', 2)
        # 結果
        qiyue
        0
        

五、類方法

  1. 為什麼會有類方法

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 建構函式
              # 初始化物件的特徵
              self.name = name
              self.age = age
              Student.sum1 += 1
      student1 = Student('劉小剛', 2)
      student2 = Student('剛小劉', 2)
      student3 = Student('小劉剛', 2)
      print(Student.sum1)
      # 結果:
      3
      
    • 每建立一個物件,類變數都會自動加一

  2. 類方法定義:

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 建構函式
              # 初始化物件的特徵
              self.name = name
              self.age = age
              Student.sum1 += 1
      
          def print_file(self):
              # 例項方法
              print("name:"+self.name)
              print("age:"+str(self.age))
      
          @classmethod
          def plus_sum(cls):
              # 類方法
              pass
      
    • @classmethod@是裝飾器的定義

    • cls:是預設引數,可以更改,代表的是類

    • 用來操作和類相關的變數

      • class Student():
            name1 = "qiyue"
            age1 = 0
            sum1 = 0
            def __init__(self, name, age):
                # 建構函式
                # 初始化物件的特徵
                self.name = name
                self.age = age
                Student.sum1 += 1
        
            def print_file(self):
                # 例項方法
                print("name:"+self.name)
                print("age:"+str(self.age))
        
            @classmethod
            def plus_sum(cls):
                # 類方法
                cls.sum1 += 1
                print(cls.sum1)
        
        student1 = Student('劉小剛', 2)
        Student.plus_sum()
        student2 = Student('剛小劉', 2)
        Student.plus_sum()
        student3 = Student('小劉剛', 2)
        Student.plus_sum()
        print(Student.sum1)
        # 結果:
        2 4 6 6
        
      • 類方法時可以用物件直接呼叫的

      • 可以看出類並沒有例項化,可以通過類直接呼叫類函式。
        當然類方法,例項也可以呼叫,但是並沒有什麼用,違反了初衷:類方法就是專門供類使用

六、靜態方法

  1. 靜態方法的定義

    • 沒有強制傳入引數、就是一個普普通通的方法

    • class Student():
          @staticmethod
          def add(x,y):
              # 靜態方法
              print("This is a static method")
      
      student1 = Student('劉小剛', 2)
      # 結果
    • 物件和類都可以呼叫這個方法

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 建構函式
              # 初始化物件的特徵
              self.name = name
              self.age = age
              Student.sum1 += 1
      
          def print_file(self):
              # 例項方法
              print("name:"+self.name)
              print("age:"+str(self.age))
      
          @classmethod
          def plus_sum(cls):
              # 類方法
              cls.sum1 += 1
              print(cls.sum1)
              pass
      
          @staticmethod
          def add(x,y):
              print("This is a static method")
      
      student1 = Student('劉小剛', 2)
      student1.add(1,1)
      Student.add(1,3)
      # 結果:
      This is a static method
      This is a static method
      
    • 靜態方法內部也可以呼叫類變數

    • 靜態方法和類關聯非常弱,可以用在和類沒有太大關係的時候用

七、成員4可見性:公開5和私有6

  1. 類的內外之分

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 建構函式
              # 初始化物件的特徵
              self.name = name
              self.age = age
              Student.sum1 += 1
      
          def print_file(self):
              # 例項方法
              print("name:"+self.name)
              print("age:"+str(self.age))
              self.do_homework()
              
          def do_homework(slef):
              # 例項方法
              pass
      
      student1 = Student('劉小剛', 2)
      
  2. 使用例項方法對例項變數的值進行修改

    • 通過物件操作例項變數是不安全的,可以通過方法來操作例項變數會更加安全,因為可以對例項變數進行限制

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 建構函式
              # 初始化物件的特徵
              self.name = name
              self.age = age
              Student.sum1 += 1
      
          def print_file(self):
              # 例項方法
              print("name:"+self.name)
              print("age:"+str(self.age))
              self.do_homework()
      
          def marking(self,score):
              # 例項方法
              if score < 0:
                  return "不能夠打負分"
              self.score = score
              print(self.name + "同學本次成績為:"+str(self.score))
      
      student1 = Student('劉小剛', 2)
      student1.marking(59)
      # 結果:
      劉小剛同學本次成績為:59
      result = student1.marking(-1)
      print(result)
      # 結果:
      不能夠打負分
      
  3. 變數私有化:

    • __:雙下劃線對變數和方法進行私有化

    • 建構函式是特有函式,所以可以訪問

    • class Student():
          # 類變數
          sum1 = 0
          # 成員屬性
          def __init__(self):
              self.__name = "劉小剛"
              self.__age = "10"
          def __marking(self):
              # 私有方法
              print("劉小剛很厲害,張小方很菜")
      
      student1 = Student()
      student1.__marking()
      # 執行結果:
      AttributeError: 'Student' object has no attribute '__marking'
      私有方法無法呼叫
      
    • # 為什麼私有成員屬性不光可以訪問,而且還能改變值
      class Student():
          # 類變數
          sum1 = 0
          # 成員屬性
          def __init__(self):
              self.__name = "劉小剛"
              self.__age = "10"
          def __marking(self):
              print("劉小剛很厲害,張小方很菜")
              pass
      student1 = Student()
      # student1.__marking()
      student1.__name = "張小方"
      print(student1.__name)
      # 結果:
      張小方
      
    • 注意:之所以可以訪問是因為,.__變數名是新建成員變數,原來的變數是無法進行訪問的,因為名字已經被修改了,不能通過動態方式建立私有變數

    • class Student():
          # 類變數
          sum1 = 0
          # 成員屬性
          def __init__(self):
              self.__name = "劉小剛"
              self.__age = "10"
          def __marking(self):
              print("劉小剛很厲害,張小方很菜")
              pass
      
      student1 = Student()
      student1.__name = "張小方"
      print(student1.__dict__)
      # 結果:
      {'_Student__name': '劉小剛', '_Student__age': '10', '__name': '張小方'}
      
    • class Student():
          # 類變數
          sum1 = 0
          # 成員屬性
          def __init__(self):
              self.__name = "劉小剛"
              self.__age = "10"
          def __marking(self):
              print("劉小剛很厲害,張小方很菜")
              pass
      student1 = Student()
      print(student1._Student__age)
      # 結果:
      10
      

八、繼承

  1. 一個程式碼塊中最好只定義一個類

  2. # c5.py
    # 父類
    class people():
        pass
    
    # c6.py
    from c5 import people
    # 繼承
    class Student(people):
        # 類變數
        sum1 = 0
        # 成員屬性
        def __init__(self):
            self.__name = "劉小剛"
            self.__age = "10"
    
        def __marking(self):
            print("劉小剛很厲害,張小方很菜")
            pass
    student1 = Student()
    
  3. 建立物件呼叫

    • # c5.py
      class Human():
          # 類變數
          sum1 = 0
          # 成員屬性
          def __init__(self, name, age):
              self.name = name
              self.age = age
          # 類方法
          def get_name(self):
              print(self.name)
      # c6.py
      from c5 import Human
      # 類、物件
      class Student(Human):
          # 類變數
          # 成員屬性
          pass
      student1 = Student("劉小剛","10")
      print(student1.sum1)
      print(student1.name)
      print(student1.age)
      # 執行結果:
      0
      劉小剛
      10   # 子類繼承父類的變數
      
  4. 一個父類有多個子類,子類的下面也能有子子類,深度不限(單繼承)

  5. from c5 import Human
    # 類、物件
    class Student(Human):
        # 類變數
    
        # 成員屬性
        def __init__(self,school,name,age):
            self.school = school
            Human.__init__(self,name,age)
    
    student1 = Student("七彩幼兒園","劉小剛","10")
    print(student1.school)
    print(student1.name)
    print(student1.age)
    # 執行結果:
    七彩幼兒園
    劉小剛
    10
    
  6. 為什麼需要在__init__()中傳入self:因為在例項化物件的時候,python自動幫忙將self傳入進去,而是用類名.例項方法 的這種操作就相當於是在呼叫例項方法,就是當成函式來呼叫,你們就要傳入引數

  7. from c5 import Human
    # 類、物件
    class Student(Human):
        # 類變數
    
        # 成員屬性
        def __init__(self,school,name,age):
            self.school = school
            Human.__init__(self,name,age)
    
        def do_homework(self):
            print("do_homework")
    
    student1 = Student("七彩幼兒園","劉小剛","10")
    # 等價
    student1.do_homework()
    Student.do_homework(student1)
    # 結果:
    do_homework
    do_homework
    
  8. 正要呼叫的缺點:當父類方法多次被呼叫時,需要多次更改父類名字

  9. 第二種呼叫父類方法的方式super,相當於代表父類這個關鍵字

    • from c5 import Human
      # 類、物件
      class Student(Human):
          # 類變數
      
          # 成員屬性
          def __init__(self,school,name,age):
              self.school = school
              # Human.__init__(self,name,age)
              super(Student,self).__init__(name,age)
      
          def do_homework(self):
              print("do_homework")
      
      student1 = Student("七彩幼兒園","劉小剛","10")
      student1.do_homework()
      # 結果:
      do_homework
      
    • super(父類名,self):也可以呼叫父類中重名的方法

    • from c5 import Human
      # 類、物件
      class Student(Human):
          # 類變數
      
          # 成員屬性
          def __init__(self,school,name,age):
              self.school = school
              # Human.__init__(self,name,age)
              super(Student,self).__init__(name,age)
      
          def do_homework(self):
              super(Student,self).do_homework()
              print("do_homework")
      
      student1 = Student("七彩幼兒園","劉小剛","10")
      student1.do_homework()
      # 結果:
      do_english_homework
      do_homework
      
  • super(父類名,self):也可以呼叫父類中重名的方法

  • from c5 import Human
    # 類、物件
    class Student(Human):
        # 類變數
    
        # 成員屬性
        def __init__(self,school,name,age):
            self.school = school
            # Human.__init__(self,name,age)
            super(Student,self).__init__(name,age)
    
        def do_homework(self):
            super(Student,self).do_homework()
            print("do_homework")
    
    student1 = Student("七彩幼兒園","劉小剛","10")
    student1.do_homework()
    # 結果:
    do_english_homework
    do_homework
    

  1. 類變數是和類相關聯的變數 ↩︎

  2. 例項變數是和物件相關聯的變數 ↩︎

  3. 檢視例項變數,和類變數,用鍵值對的方式返回 ↩︎

  4. 成員是指變數和方法 ↩︎

  5. 公開的那麼就可以任意呼叫 ↩︎

  6. 私有的,則不行 ↩︎

相關文章