1. 程式人生 > >面向物件--第一部分

面向物件--第一部分

面向物件

面向物件

  • 與面向過程對比

    • 面向過程:數學邏輯的對映,學會做個好員工。

    • 面向物件:生活邏輯的對映,學會做個好領導。

  • 生活例項

    • 類: 手機 電腦

    • 物件: 習大大、普京 二狗的iphoneX 生輝桌上的電腦

  • 官方定義

    • 類:具有相同特徵(屬性和行為)事物的抽象

    • 物件:某個類的具象

  • 程式語言

    • 類:是一種自定義的資料型別

    • 物件:某個類型別的變數

面向物件語法

  • 類的定義

    class 類名:
    pass
  • 語法說明

    • 定義類需要使用關鍵字class

    • 類名:原則上符合識別符號命名規範即可,但是通常我們都採用大駝峰風格命名,如:UserName

    • 類名後面的':'不要忘記

    • 類的內容要進行整體縮排

    • 行為通過方法體現

    • 屬性通過變數體現,需要動態新增

    • 成員訪問:

      • 屬性:物件.屬性名

      • 方法:物件.方法名()

    • 示例:

      # 定義類
      class Person:
          # 行為時通過方法體現的
      # 吃飯
          def
      eat(self): print('紅燒雞腿我喜歡吃') ​ # 睡覺 def sleep(self): print('睡覺是一種生活態度') # 建立物件 hui = Person() ​ # 屬性時動態新增的 hui.age = 30 hui.height = 170 print(hui.age) ​ # 呼叫物件方法 hui.eat()
  • self使用

    class Person:
        def run(self):
            # self表示當前物件,就是呼叫該方法的物件
            print
    ('{}每天以2m/s的速度慢跑5km'.format(self.name)) ​ def introduce(self): # 不但可以訪問成員屬性 print('我叫{}今年18歲'.format(self.name)) # 還可以呼叫成員方法 # self引數可以使用其他名字,呼叫方法時不需要傳遞 self.run() ​ hui = Person() hui.name = '生輝' # hui.run() ​ fei = Person() fei.name = '趙飛' # fei.run() fei.introduce()      
  • __str__方法

    class Person:
          # 預設列印物件,顯示類名+地址
          # 重寫該方法,列印該方法的返回值
          def __str__(self):
              return '我叫{},今年{}歲'.format(self.name, self.age)
    ​
      james = Person()
      james.name = '勒布朗.詹姆斯'
      james.age = 33
      print(james)
  • __init__方法        

    class Cat:
        def __str__(self):
            return 'name:{},age:{},color:{}'.format(self.name, self.age, self.color)
    ​
        # 構造方法:建立物件後,會自動呼叫該方法完成初始化設定
        def __init__(self, name, age, color):
            # print('__init__', name, age, color)
            self.name = name
            self.age = age
            self.color = color
    ​
    # 這種方案比較繁瑣
    # jiafei = Cat()
    # jiafei.name = '加菲'
    # jiafei.age = 2
    # jiafei.color = '橘黃色'
    # print(jiafei)
    ​
    jiafei = Cat('加菲', 2, '橘黃色')
    print(jiafei)
  • __del__方法

    class Pig:
          # 析構方法:當物件釋放時,系統會自動呼叫
          # 若手動使用del刪除:則會立即呼叫該方法
          # 該方法一般做資源釋放操作,如:資料庫斷開連線,檔案關閉
          def __del__(self):
              print('大師兄,我不行了')
    ​
      bajie = Pig()
      del bajie
      print('八戒,一路走好')
  • 思考:小明手裡有2張牌,左手♥K,右手♠A,小明交換兩手的牌後,手裡分別有什麼?

    • 先找到物件:小明、左手、右手、♥K、♠A

    • 根據物件抽象類:人、手、牌

    • 根據需求完善設計對應的類

    • 示例

      # 撲克牌
      class Poker:
          def __init__(self, color, number):
              self.color = color
              self.number = number
      ​
          def __str__(self):
              return '{}{}'.format(self.color, self.number)
      ​
      # 建立兩張牌
      p1 = Poker('', 'K')
      p2 = Poker('', 'A')
      ​
      # 手的類
      class Hand:
          def __init__(self, poker=None):
              self.poker = poker
      ​
          def hold_poker(self, poker):
              self.poker = poker
              
      # 建立兩隻手
      left_hand = Hand(p1)
      right_hand = Hand(p2)  
      ​
      # 人的類
      class Person:
          def __init__(self, name, left_hand, right_hand):
              self.name = name
              self.left_hand = left_hand
              self.right_hand = right_hand
      ​
          # 展示手中的牌
          def show(self):
              print('{}張開手'.format(self.name), end=' ')
              print('左手:{}'.format(self.left_hand.poker), end=',')
              print('右手:{}'.format(self.right_hand.poker))
      ​
          # 交換兩手的牌
          def swap(self):
              self.left_hand.poker, self.right_hand.poker = self.right_hand.poker, self.left_hand.poker
              print('{}交換兩手的牌'.format(self.name))
              
      # 建立小明物件
      xiaoming = Person('小明', left_hand, right_hand)
      ​
      # 展示手中的牌
      xiaoming.show()
      ​
      # 交換兩手的牌
      xiaoming.swap()
      ​
      # 再次展示牌
      xiaoming.show()
  • 練習:設計一個數學類,屬性有兩個數,方法:加、減、乘、除,展示成員

    第一種:
    class Math:
        def __init__(self,one,two):
            self.one = one
            self.two = two
        def add(self):
            print('{}+{}'.format(self.one,self.two))
        def sub(self):
            print('{}-{}'.format(self.one, self.two))
        def mul(self):
            print('{}*{}'.format(self.one, self.two))
        def div(self):
            print('{}/{}'.format(self.one, self.two))
    show = Math(10,5)
    show.add()
    show.mul()
    show.div()
    show.sub()
    第二種:
    class Number:
        def __init__(self,num1,num2):
            self.num1 = num1
            self.num2 =num2【
        def add(self):
            return self.num1 + self.num2
    ​
        def sub(self):
            return self.num1 - self.num2
    ​
        def mul(self):
            return self.num1 * self.num2
    ​
        def div(self):
            if self.num2 == 0:
                return None
            return self.num1 / self.num2
    a = Number(3,3)
    print(a.add())
    print(a.sub())
    print(a.mul())
    print(a.div())
  • 實現平方和

    #對外提供簡單易用的介面
    class Number:
        def __init__(self,num1,num2):
            self.num1 = num1
            self.num2 =num2
        def add(self):
            return self.num1 + self.num2
    ​
        def sub(self):
            return self.num1 - self.num2
    ​
        def mul(self):
            return self.num1 * self.num2
    ​
        def div(self):
            if self.num2 == 0:
                return None
            return self.num1 / self.num2
        @classmethod
        def pingfanghe(cls,num1,num2):
            a = cls(num1,num1)
            m = a.mul()
            b = cls(num2,num2)
            n = b.mul()
            c = cls(m,n)
            ret = c.add()
            return ret
    ret = Number.pingfanghe(2,3)
    print(ret)

常用內建函式

  • 內建函式:在類中,特定時機自動回觸發的函式。

    • 設定、獲取、銷燬屬性時自動觸發的方法:

      class Person:
          def __str__(self):
              return '姓名:{}'.format(self.name)
      ​
          def __init__(self, name):
              self.name = name
      ​
          def __del__(self):
              print('物件即將銷燬')
      ​
          # 當訪問不存在的屬性時會自動觸發該方法
          def __getattr__(self, item):
              if item == 'age':
                  return 18
              else:
                  return '你猜'# 設定屬性時會自動觸發該方法
          def __setattr__(self, key, value):
              # print(key, value)
              self.__dict__[key] = value
      ​
          # 銷燬物件的指定屬性時會自動觸發
          def __delattr__(self, item):
              print(item, '屬性即將銷燬')
              
      xiaoming = Person('小明')  
      ​
      # print(xiaoming.age)
      # print(xiaoming.weight)
      xiaoming.age = 20# 存放了所有的物件屬性
      # print(xiaoming.__dict__)
      # print(xiaoming.age)
      del xiaoming.age
  • 將物件當做字典操作,特定時機自動觸發的函式

    class Person:
        # 將物件當做字典操作,新增或設定屬性時自動觸發
        def __setitem__(self, key, value):
            print(key, value)
            self.__dict__[key] = value
    ​
        # 將物件當做字典操作,獲取屬性時自動觸發
        def __getitem__(self, item):
            # print(item)
            return self.__dict__.get(item)
    ​
        # 將物件當作字典操作,銷燬屬性時自動觸發
        def __delitem__(self, key):
            print(key, '即將銷燬')
            del self.__dict__[key]
    ​
    xiaoming = Person()
    ​
    xiaoming['name'] = '小明'
    # print(xiaoming.name)
    print(xiaoming['name'])
    ​
    del xiaoming['name']
  • 將物件當做函式呼叫

    class Person:
        # 將物件當做函式呼叫時,會自動觸發該方法
        def __call__(self, *args, **kwargs):
            # print('__call__', args)
            return sum(args)
    ​
    xiaoming = Person()
    # 如果想這樣呼叫,必須重寫__call__方法
    ret = xiaoming(1, 2, 3)
    print(ret)
  • 判斷一個物件是否可以呼叫,是否擁有某屬性,是否是函式

    def test():
        pass# 判斷一個物件能否被呼叫
    print(callable(xiaoming))
    print(callable(test))
    ​
    # 判斷一個物件是否擁有__call__屬性
    print(hasattr(test, '__call__'))
    print(hasattr(xiaoming, '__call__'))
    ​
    # 判斷一個物件是否是函式
    from inspect import isfunction
    print(isfunction(test))
    print(isfunction(xiaoming))

練習

  • 第一題

    • 設計一個學生類

      • 屬性:姓名、學號、年齡、成績

    • 設計一個班級類

      • 屬性:班級代號,所有學生

    • 要求:實現向班級中新增學生、刪除學生、檢視學生、按照指定條件排序

      #學生類
      class Student :
      ​
          def __init__(self,name,number,age,grade):
              self.name = name
              self.number = number
              self.age =age
              self.grade = grade
          def __str__(self):
              return 'name:{},number:{},age:{},grade:{}'.format(self.name,self.number,self.age,self.grade)
      ​
      #班級類
      class Class :
          def __init__(self,title):
              self.title =title
              self.student_list = []
              self.student_dict = {}
          def add_stu(self,stu):
              self.student_list.append(stu)
              self.student_dict[stu.number] = stu
          #學生排序
          def sort_stu(self,key=None,reverse =False ):
              self.student_list.sort(key=key , reverse=reverse)
          #查詢學生
          def get_stu(self,number):
              return self.student_dict.get(number)
          #刪除學生
          def del_stu(self,number):
              #從字典中彈出並刪除
              s = self.student_dict.pop(number)
              #從列表刪除
              self.student_list.remove(s)
          def show_stu(self):
              for stu in self.student_list:
                  print(stu)
      ​
      from  random import randint
      #建立一個班級
      banji = Class('python-1805')
      #按照成績
      banji.sort_stu(key=lambda  banji: banji.grade,reverse=True)
      for i in range(10):
          name = 'stu' + str(i+1)
          number = 100 + i
          age = randint(20,30)
          grade = randint(0,100)
          #建立學生物件
          stu = Student(name,number,age,grade)
          #將學生新增到班級的列表中
          banji.add_stu(stu)
      ​
      banji.show_stu()
  • 第二題

    • 將歌詞解析封裝成類,要求:提供一個方法(根據時間返回歌詞)

      • 提示:封裝兩個類:歌詞類、歌詞管理類

        #歌詞類
        class Lrc:
            def __init__(self,sec,lrc):
                self.sec = sec
                self.lrc = lrc
            def __str__(self):
                return "{}:{}".format(self.sec,self.lrc)
          #歌詞管理類
          class LrcManager:
              def __init__(self,lrc_file):
                  self.lrc_dict = {}
                  self.time_list = []
                  self.song_dict = {}
                  self.lrc_file =lrc_file
                  self.jiexi = ()
        ​
              def jiexi(self):
                  fp = open(self.lrc_file)
                  lrc_list = fp.readlines()
              #根據時間返回歌詞物件
              def get_lrc(self,sec):
                  for t in self.time_list:
                      if t <sec:
                          return self.lrc_dict[t]