面向對象編程(oop)

類和麪向對象(oop)

概述

  • oop思想
    任意一個任務,首先想到的是任務的構成和實現過程。html

  • 類和對象的概念python

    • 類:抽象名詞,表明一個集合,表明一類事物。
    • 對象:具象的事物,單個個體。
  • 類的內容設計模式

    • 屬性(變量):代表事物特徵
    • 方法(函數):代表事物功能
  • 類的命名函數

    • 大駝峯比較規範。
    • 必須用class關鍵字。
    • 由屬性和方法組成,其餘不準出現。
    • 成員屬性定義可直接用變量賦值,若是沒有值需使用None。
  • 訪問類和對象的成員oop

    # 對象成員檢查
    obj.__dict__
    # 類成員檢查
    class_name.__dict__
  • 實例設計

    # 定義一個簡單的類
     class StudentPython():
     name = None
     age = 18
     def Studentplay(self):
         print("learning python")
    
     # David爲對象,此時實例化類
     David = StudentPython()
     print(David.name)
     print(David.age)
     David.Studentplay()

類和對象的成員分析

  • 類和對象均可以儲存成員,成員能夠歸類全部也能夠歸對象全部。code

  • 建立對象時,類中的成員不會放入對象中,而是獲得一個空對象。orm

  • 經過對象對類中成員從新賦值或者經過對象添加成員時,對應成員會保存在對象中,而不會修改類成員。htm

  • 實例對象

    class Teacher():
        name = "aaa"
        age = 28
        def TeacherSay(self):
            self.name = "Mary"
            self.age = 20
            print("My name is {0}".format(self.name))
            print("My age is {0}".format(self.age))
      
    t = Teacher()
    print(t.name)  
    print(t.age)
    t.TeacherSay()
    
    '''
    aaa
    28
    My name is Mary
    My age is 20
    '''

關於self

  • self在對象的方法中表示當前對象自己,若是經過對象調用方法,那麼該對象會自動傳入到當前方法的第一個參數中。

  • self並非關鍵字,理論上能夠用任何一個普通變量名代替。

  • 方法中有self形參的稱爲非綁定類的方法,能夠經過對象訪問,沒有self的稱爲綁定類方法,只能經過類訪問。

  • 實例

    class Teacher():
        name = "aaa"
        age = 28
        def TeacherSay(self):
            self.name = "Mary"
            self.age = 20
            print("My name is {0}".format(self.name))
            print("My age is {0}".format(self.age))
        def TeacherSayAgain():
            print(__class__.name)
            print(__class__.age)
            print("learning python")
    
    t = Teacher()
    t.TeacherSay()
    # 調用綁定類方法經過類訪問
    Teacher.TeacherSayAgain()
    
    '''
    My name is Mary
    My age is 20
    aaa
    28
    learning python
    '''

面向對象的三大特性

封裝,繼承,多態

  • 封裝
    • 三個級別:公開(public),受保護(protected),私有(private)。

    • 判別對象的位置:對象內部,對象外部,子類中。

    • 私有:私有成員是最高級別的封裝,只能在當前類或對象中訪問,外部不能訪問。python的私有不是真私有,是一種爲name mangling的更名策略。

      class Person():
          # name爲共有成員
          name = "David"
          #__age爲私有成員
          __age = 18
    • 受保護:將對象成員進行必定級別的封裝,在父類和子類中能夠訪問,外部不能訪問。

    • 公開:對對象成員沒有任何操做,任何地方均可以訪問。

  • 繼承
    • 繼承就是一個類能夠得到另一個類中的成員屬性和方法。

    • 被繼承的爲父類(基類或超類),用於繼承的類爲子類(派生類)。

    • 全部的類都繼承自object類,即全部的類都是object類的子類。

    • 子類繼承父類後並無將父類成員徹底賦值到子類,而是經過引用關係訪問調用。

    • 子類一旦繼承父類,可使用父類中除私有成員外的全部成員屬性和方法,子類還能夠定義獨有的成員屬性和方法。

    • 子類中定義的成員若是和父類成員相同,則優先使用子類成員。

    • 若是想在子類中擴充父類方法,能夠在定義新方法時訪問父類成員來進行代碼重用,能夠父類名.父類方法也能夠super().父類方法的格式調用。
      super不是關鍵字,而是一個類。super的做用是獲取MRO(MethodResolutionOrder)列表中的第一個類

      class Person():
          name = "None"
          __age = 18
          _score = 0
          def Study(self):
              print("learning python")
      
      class Student(Person):
          def HaveTest(self):
              print("have to take exam")
          # 擴充父類函數,方法一二
          def Study(self):
              Person.Study(self)# 注意這裏有self
              self.HaveTest()
              '''
              super().Study()# 注意這裏沒有self
              # super(Student, self).Study()也能夠
              self.HaveTest()
              '''    
                             
      David = Student()
      print(David.name)
      David.Study()
      
      '''
      None
      learning python
      have to take exam
      '''
    • 繼承中的查找順序:子類優先查找本身的變量,沒有則查找父類變量;
      子類中若是構造函數沒有定義,則按照MRO順序查找調用父類的構造函數,子類有定義則不繼續向上查找。
      構造函數:每次實例化第一個被自動調用的函數

    • 單繼承和多繼承:單繼承每一個類只能繼承一個類,多繼承每一個類能繼承多個類;單繼承邏輯清晰語法簡單但功能不能受限,多繼承擴展方便但關係混亂且會出現菱形繼承(鑽石繼承)問題。

    • MRO:是在多繼承中用於保存繼承順序的一個列表;
      MRO計算原則:子類永遠在父類前;若是多個父類則根據括號內類的書寫順序存放;若是多個類繼承了同一個父類,孫子類中只會選取括號內第一個父類的父類。

  • 多態
    • 多態就是同一個對象在不一樣狀況下有不一樣狀態出現。

    • Mixin設計模式:主要採用多繼承方式對類功能進行擴展。首先必須表示某一單一功能,若是有多個功能則寫多個Mixin,當子類沒有繼承某一Mixin類也能照常工做。

      class Person():
          def __init__(self, name, age):
              self.name = name
              self.age = age
          def Play(self):
              print("have fun")
          def Sleep(self):
              print("sleeping...")
      # 建立一個Mixin
      class TeacherMixin():
          def Work(self):
              print("teaching somebody")
      
      class StudentMixin():
          def Study(self):
              print("learning python")
      
      class Student(Person, StudentMixin):
          pass
      class Teacher(Person):
          def __init__(self):
              self.name = "Alex"
      
      David = Student("David", 18)
      print("my name is {0}, my age is {1}".format(David.name, David.age))
      David.Study()
      David.Play()
      print("*" * 20)
      Alex = Teacher()
      print("my name is {0}".format(Alex.name))
      Alex.Sleep()
      
      '''
      my name is David, my age is 18
      learning python
      have fun
      ********************
      my name is Alex
      sleeping...
      '''

類相關函數

  • issubclass:檢測一個類是不是另外一個類的子類。
  • isinstance:檢測一個對象是不是一個類的實例。
  • hasattr:檢測一個對象是否有成員xxx。
  • dir:獲取對象的成員列表

類的成員描述符(屬性)

  • 類的成員描述符是爲了在類中對類的成員屬性進行相關操做

  • 三種方式:使用類實現描述器;使用屬性修飾符;使用property函數property(fget, fset, fdel, doc)

    class Person():
        '''
        property函數實例
        定義一個Person類,具備name,age屬性,
        對於任意輸入的name都但願以大寫字母保存
        '''
        def fget(self):
            # 返回操做後的屬性
            return self._name
        def fset(self, name):
            # 傳入須要操做的屬性
            self._name = name.upper()
        def fdel(self):
            self._name = "NoName"
        name = property(fget, fset, fdel, "None")
        age = 18
      
    David = Person()
    David.name = "David"
    print("my name is {0}".format(David.name))
    '''
    my name is DAVID
    '''

類的內置屬性

__dict__:以字典的方式顯示類成員的組成
__doc__:獲取類的文檔信息
__name__:獲取類的名稱,若是在模塊中使用則獲取模塊名稱
__bases__:以元組方式顯示類的全部父類

類的經常使用魔術方法

  • 魔術方法就是不須要認爲調用,在特定的狀況下自動觸發的方法,統一特徵是方法名被先後兩個下劃線包裹。
    __init__:構造函數
    __new__:對象實例化方法
    __call__:對象當函數時使用
    __str__:對象被看成字符串時使用
    __repr__:返回字符串
    __getattr__:訪問一個不存在的屬性時觸發,此時不會報錯
    __gt__:進行大於判斷的時候觸發
    __setattr__:對成員屬性設置的時候觸發

    # __setattr__示例
    class A():
        def __setattr__(self, name, value):
            print("設置屬性{0}爲{1}".format(name, value))
            '''
            這樣會致使死循環
            self.name = value
            '''
            # 爲了不這種狀況,使用父類魔法函數
            super().__setattr__(name, value)
    a = A()
    a.age = 18

類和對象的三種方法

  • 實例方法:必需要建立實例對象才能調用,第一個參數必須是實例對象,該參數名通常約定爲self,若是方法裏面有初始化函數也必須對初始化函數進行傳參。且只能由實例對象調用

  • 類方法:使用裝飾器@classmethod,第一個參數必須是當前類對象,該參數名通常約定爲cls,能夠由實例對象和類對象調用。

  • 靜態方法:使用裝飾器@staticmethod,沒有self和cls參數,能夠由實例對象和類對象調用。
    參考博客Python 實例方法、類方法、靜態方法的區別與做用

    class Person():
        def Work(self):
            print("have to work")
        @classmethod
        def Study(cls):
            print("have to study")
        @staticmethod
        def Sleep():
            print("sleeping...")
    # 實例方法
    p = Person()
    p.Work()
    #Person.Work()會報錯
    # 類方法
    p.Study()
    Person.Study()
    # 靜態方法
    p.Sleep()
    Person.Sleep()
相關文章
相關標籤/搜索