1. 程式人生 > 其它 >反射實操與面向物件雙下方法

反射實操與面向物件雙下方法

反射實操

利用面向物件的反射編寫系統終端

 反射提供了一種不考慮程式碼,對資料和功能進行操作的方式

      class WinCmd(object):  # 定義一個WinCmd的類
          def ls(self):
              print('windows ls命令')

          def dir(self):
              print('windows dir命令')

          def cd(self):
              print('windows cd命令')


      class Linux(object):  # # 定義一個Linux的類
          def ls(self):
              print('linux ls命令')

          def dir(self):
              print('linux dir命令')

          def cd(self):
              print('linux cd命令')


      obj1 = WinCmd()  # 生成物件
      print(obj1)  # <__main__.WinCmd object at 0x0000017B0E7A23C8>
      obj2 = Linux()  # 生成物件
      print(obj2)  # <__main__.Linux object at 0x0000017B0E7A2470>


      def run(obj):
          while True:
              cmd = input('cmd order>>>: ').strip()  # 獲取使用者命令
              if hasattr(obj, cmd):  # 如果物件的名稱空間有該字串所對應的資料或者功能,結果為True
                  func_name = getattr(obj, cmd)  # 如果物件的名稱空間有該字串所對應的資料或者功能,取其對應的資料或者功能
                  func_name()
              else:
                  print('cmd order is not be found')


      run(obj1)  # 類似於win的cmd命令
      run(obj2)  # 類似linux的命令視窗

面向物件部分雙下方法(內建方法)

 面向物件中有一些方法名字是類似於__……__的結構。這類方法也被人稱為魔法方法。因為有些雙下方法是不需要呼叫的,而是在特殊條件下自動觸發的。比如__init__方法會在物件例項化的時候自動觸發。

      class MyClass(object):
          person: True
          def __init__(self, name, age, gender):  # 物件例項化
              self.name = name
              self.age = age
              self.gender = gender

          def __str__(self):  # 物件展示的時候自動觸發
              print('列印操作')
              return 'print'

          def __del__(self):  # 主動或者被動(執行結束,垃圾處理機制作用)刪除物件的時候觸發
              print('刪除操作')
              pass

          def __getattr__(self, item):  # 獲取資料或者功能,找不到時觸發
              print('愛而不得')
              pass

          def __call__(self, *args, **kwargs):  # 物件被加括號呼叫的時候觸發
              print('呼叫物件')
              pass

          def __enter__(self):  # with方法操作物件時觸發
              print('檔案管理操作')
              pass

          def __exit__(self, exc_type, exc_val, exc_tb):  # 結束操作物件時觸發
              print('檔案管理操作結束')
              pass

          def __getattribute__(self, item):  # 查詢資料或功能時觸發,無論能不能找到
              print('大膽愛')
              pass

          '''在__getattr__方法和__getattribute__方法同時存在時,後者會頂替前者執行作用,前者不執行'''

      obj1 = MyClass('oliver', 25, 'male')

      print(obj1)
      '''釋放__getattr__方法,注掉__getattribute__方法'''
      obj1.name  # 能獲取到
      obj1.salary  # 獲取不到  愛而不得  (__gertattr__)

      '''釋放__getattribute__方法,注掉__getattr__方法'''
      obj1.name  # 大膽愛
      obj1.salary  # 大膽愛

      '''釋放__getattribute__方法,__getattr__方法'''
      obj1.name  # 大膽愛
      obj1.salary  # 大膽愛

      '''在__getattr__方法和__getattribute__方法同時存在時,後者會頂替前者執行作用,前者不執行'''

      obj1()  # 呼叫物件

      with obj1 as f:
          print('進行檔案操作')  # 檔案管理操作(__enter__)  進行檔案操作  檔案管理操作結束(__exit__)

更多方法:面向物件更多雙下方法

問題處理

問題一: 使字典具備句點符取值的功能

      class MyDict(dict):
          def __getattr__(self, item):  # 取物件中的名字是'item'的資料或者方法
              return self.get(item)  # 獲得該名字所對應的資料或者功能名

          def __setattr__(self, key, value):  # 在名稱空間中新增資料
              self[key] = value  # 以鍵值對的方式新增


      obj1 = MyDict('oliver', 25)
      print(obj1)  # {'name': 'oliver', 'age': 25}
      print(obj1.name)  # oliver
      print(obj1.age)  # 25

      obj1.gender = 'male'  # 通過點的方式對物件的名稱空間進行操作,新增資料
      print(obj1)  # {'name': 'oliver', 'age': 25, 'gender': 'male'}
      print(obj1.salary)  # None

問題二:程式碼補全問題

'''
題目:
        class Context:
            pass

        with Context() as ctx:
            ctx.do_something()
'''

'''
解決步驟:
      分析:
              類 Context -----> Context():產生物件 -----> with 操作 Context():需要有 __enter__ 和__exit__
              -----> ctx.do_something() 物件用點的方式訪問do_something,且do_something加了括號,所以物件有
              do_something方法
'''

      class Context:
          def __enter__(self):
              return self

          def __exit__(self, exc_type, exc_val, exc_tb):
              return 123

          def do_something(self):
              print('程式碼已補全')


      with Context() as ctx:
          ctx.do_something()  # 程式碼已補全