天天看點

python基礎程式設計day18

類
    class Student:
        def __init__(self, n, a, s):
            '''初始化方法'''
        def __del__(self):
            '析構方法'
        def set_score(self, s):
            ...
        def get_score(self):
            return self.score

  執行個體方法, 描述或規定對象能有哪些行為
  執行個體屬性, 記錄每個對象自身的資料(屬性)
     添加和修改
        obj.attr = 表達式
     删除
        del obj.attr
  初始化方法__init__(self, ....) 把所有對象添加相同個數的屬性
  析構方法 __del__(self)   在對象銷毀前釋放對象自身占用的資源
  
  預置的執行個體屬性:
    __dict__ 綁定存儲執行個體屬性的字典
    __class__ 綁定建立此對象的類

  isinstance(obj, 類或元組)
  type(obj)      

新的一天 筆記:

類屬性

類屬性是類的屬性,此屬性屬于類,不屬于此類的執行個體
  
  作用:
    通常用來存儲該類建立的對象的共有屬性
  說明:
    類屬性,可以通過該類直接通路
    類屬性可以通過此類的執行個體直接通路(取值不能指派)
    類屬性可以通過此類對象的'__class__' 屬性間接通路
    執行個體方法和類方法都屬于類的屬性
  示例見:
  ```
  class Car:
      total_count = 0  # 建立類屬性,用來儲存汽車的數量
  
  
  # 類屬性,可以通過該類直接通路
  print(Car.total_count)  # 0  # 取類屬性的值
  
  Car.total_count += 100  # 修改類屬性
  
  print(Car.total_count)  # 100
  
  ```      

類的文檔字元串:

類内第一個沒有指派給任何變量的字元串為類的文檔字元串
  類的文檔字元串綁定在類的__doc__屬性上

  示例:
   class Dog:
       '這是Dog類的文檔字元串'
   print(Dog.__doc__)
    >>> help(Dog)      
h1 = Human('Tarena', 17)
  h1.show_info()  # Tarena 今年 17 歲
  # h1.Age = 18  # 報錯,不允許添加此Age屬性
  h1.show_info()  # Tarena 今年 17 歲
  
  ```      

類方法 @classmethd

類方法是用于描述類的行為的方法,類方法屬于類,不屬于該類創
    建的對象

  說明:
    類方法需要使用@classmethod裝飾器定義
    類方法至少有一個形參,第一個形參用于綁定類,約定寫為'cls'
    類和該類的執行個體都可以調用類方法
    類方法不能通路此類建立的對象的執行個體屬性
  示例見:

  ```
  class A:
      v = 0  # 類屬性
  
      @classmethod
      def get_v(cls):  # cls為class簡寫
          return cls.v
  
      @classmethod
      def set_v(cls, value):
          cls.v = value
  
  print(A.get_v())  # ???
  a = A()
  print(a.get_v())
  A.set_v(100)
  print(A.get_v()) # 100
  a.set_v(200)
  print(A.get_v())  # 200
  ```      

靜态方法 @staticmethod

靜态方法是定義在類的内部的函數,此函數的作用域是類的内部

  說明:
    靜态方法需要使用@staticmethod 裝飾器定義
    靜态方法與普通函數定義相同,不需要傳入self執行個體參數和cls類參數
    靜态方法隻能憑借類或類建立的執行個體調用
    靜态方法不能通路類屬性和執行個體屬性
  示例見:
  ```
  class A:
      @staticmethod
      def myadd(x, y):
          return x + y
      
  print(A.myadd(100, 200))  # 300
  a = A()
  print(a.myadd(3, 4))  # 7
  
  
  ```      

小結:

函數       操作全局變量和局部變量
  執行個體方法    操作全局變量,局部變量,執行個體屬性,類屬性
  類方法      操作全局變量,局部變量,類屬性
  靜态方法    操作全局變量,局部變量(作用域在類内)      

class 用類來描述一個學生的資訊(可以修改之前的Student類)

class Student:
     ... 此處自己實作
  學生資訊有: 姓名,年齡,成績

  将這些學生對象存于清單中,可以任意添加和删除學生資訊
    1. 列印學生的總個數
    2. 列印出所有學生的平均成績
  (建議用類來封裝學生資訊,用函數或類方法對學生資料進行操作)      

繼承(inheritance) 和 派生(derived)

什麼是繼承和派生
    繼承是從已有類中派生出新類,新類具有原類的屬性和行為.
    派生就是從一個已有類中衍生出新類,在新類上可以添加新的屬性和行為
  
  說明:
    繼承的目的是延續舊的類的功能
    派生的目地是在舊類的基礎上添加新的功能
  作用:
    用繼承派生機制,可以将一些共有功能加在基類中,實作代碼的共享
    在不改變基類的代碼的基礎上改變原有類的功能
  
  名詞:
    基類(base class)/超類(super class)/父類(father class)
    派生類(derived class)/子類(child class)      

單繼承

文法:
    class 類名(基類名):
        語句塊
  說明:
    單繼承是指派生類由一個基類衍生出新類
  示例見:
  ```
  class Human:
      '''定義一個'人'類,用來描述人的行為'''
      def say(self, what):
          print("say:", what)
      
      def walk(self, distance):
          print("走了", distance, '公裡')
  
  class Student(Human):
      def study(self, subject):
          print("學習:", subject)
  
  class Teacher(Human):
      def teach(self, language):
          print("教:", language)
  
  h1 = Human()
  h1.say('今天天氣真好!')
  h1.walk(5)
  s1 = Student()
  s1.walk(4)
  s1.say("走的有點累")
  s1.study('python')
  
  t1 = Teacher()
  t1.teach("面向對象")
  t1.walk(6)
  t1.say('晚上吃點啥好!')
  ```

繼承說明:
  Python3任何類都直接或間接的繼承自object類
  object類是一切類的超類

類的__base__屬性
  __base__屬性用來記錄此類的基類

檢視全部python3内建類的繼承關系的方法:
  >>> help(__builtins__)

思考:
  list 類裡隻有append向末尾追加資料的方法,但沒有向清單頭部
  添加元素的方法,試想能否為例表在不改變原有功能的基礎上添加
  一個insert_head(n) 方法來實作向頭部插入資料?
  即:
    class MyList(list):
        def insert_head(self, n):
            ...
    myl = MyList(range(3, 6))
    print(myl)  # [3, 4, 5]
    myl.insert_head(2)
    print(myl)  # [2, 3, 4, 5]
    myl.append(6)
    print(myl)  # [2, 3, 4, 5, 6]      

覆寫 override

什麼是覆寫
    覆寫是指在有繼承關系的類中,子類中實作了與基類同名的方法,在
    子類的執行個體調用該方法時,實際調用的是子類中的覆寫版本,這種現象
    叫覆寫
  作用:
    實作和父類同名,但功能不同的方法
  示例見:
  ```
  class A:
      def work(self):
          print("A.work被調用")
  
  class B(A):
      def work(self):
          '''此方法會覆寫父類的work方法'''
          print("B.work被調用!!!!")
      pass
  
  b = B()
  b.work()  # 請問調用誰?  B.work被調用
  
  a = A()
  a.work()  # 請問調用誰?
  
  ```      

提出問題

問題:
  當覆寫發生時,子類對象能否調用父類中的方法?

子類對象顯式調用父類方法的方式:
   基類名.方法名(執行個體, 實際調用傳參, ...)      

super 函數:

super(cls, obj)  傳回綁定超類的執行個體(要求obj必須為cls類型
                   的執行個體)
  super()       傳回綁定超類的執行個體,等同于:
                   super(__class__, 執行個體方法的第一個參數),
                   必須在方法内調用
  作用:
    借助super() 傳回的執行個體間接調用其父類的覆寫方法      

顯式調用基類的初始化方法:

當子類中實作了__init__ 執行個體方法時,基類的初始化方法并不會
  被調用.如何顯式調用父類的初始化方法?

  示例見:
  ```
  class Human(object):
      def __init__(self, n, a):
          self.name = n
          self.age = a
          print("Human.__init__被調用", n, a)
  
      def show_info(self):
          print("姓名:", self.name)
          print("年齡:", self.age)
  
  class Student(Human):
      def __init__(self, n, a, s):
          super().__init__(n, a)
          print("Student.__init__(", n, a, s, ')')
          self.score = s
  
      def show_info(self):
          super().show_info()
          print("成績:", self.score)
  
  s1 = Student('李四', 25, 100)
  s1.show_info()
  # print(dir(s1))
  
  # h1 = Human('小張', 20)  # 請問是否會調用__init__方法?
  # h1.show_info()
  
  ```      

用于類的函數:

issubclass(cls, class_or_tuple) 判斷一個類是否繼承自其
      它的類,如果此類cls是class或tuple中的一個類的派生子
      類則傳回True, 否則傳回False
  示列:
    class A:
        pass
    class B(A):
        pass
    class C(B):
        pass
    issubclass(C, B)  # True
    issubclass(B, C)  # False
    issubclass(C, A)  # True 
    issubclass(B, (int, float, A))  # True
    issubclass(bool, int)  # True

練習(easy):
  寫一個類Bicycle類(自行車類), 有run方法,調用時顯示騎行裡程
    class Bicycle:
        def run(self, km):
            print("自行車騎行了", km, '公裡')
 再寫一個類EBicycle(電動自行車類), 在Bicycle類的基礎上添加
    電池電量volume屬性,
    有兩個方法:
      1. fill_charge(vol)  用來充電,vol為電量(度)
      2. run(km) 方法每騎行10km 消耗電量1度,同時顯示目前
  電量,當電量耗盡時,則調用Bicycle的run方法(人力騎行)
    class EBicycle(Bicycle):
        ... # 此處自己實作,邏輯要符合現實
    b = EBicycle(5)  # 新買的電動車内有5度電
    b.run(10)  # 電動騎行了10公裡,還剩4度電
    b.run(100)  # 電動騎行了40公裡,還剩0度電,人力騎行60km
    b.fill_charge(10)  # 電動自行車充電10度
    b.run(50)  # 電動騎行了50公裡,還剩5度電