天天看點

深度之眼-Python學習筆記——第七章 類-面向對象的程式設計第七章 類——面向對象的程式設計

第七章 類——面向對象的程式設計

引子

Why:面向對象更符合人類對客觀世界的抽象和了解

  • 一切皆對象

    一隻小狗,一把椅子,一張信用卡,一條巧克力。。。

  • 一切對象,都有自己内在的屬性

    狗狗的品種、椅子的質地、信用卡的額度、巧克力的口味。。。

  • 一切行為,皆是對象的行為

    狗狗蹲下、椅子移動位置、刷信用卡、巧克力融化了。。。

How:類是對象的載體

不同年齡、膚色、品質的貓,每一隻都是一個對象

他們有一個共同的特征:都是貓

我們可以把一類對象的公共特征抽象出來,建立通用的類

# 建立類
class Cat():
    """模拟貓"""
    
    def __init__(self, name):
        """初始化屬性"""
        self.name = name
    
    def jump(self):
        """模拟貓跳躍"""
        print(self.name + " is jumping") 
           
# 用類建立執行個體
my_cat = Cat("Loser")
your_cat = Cat("Lucky")
           
# 調用屬性
print(my_cat.name)
print(your_cat.name)
           
Loser
Lucky
           
# 調用方法
my_cat.jump()
your_cat.jump()
           
Loser is jumping
Lucky is jumping
           

7.1 類的定義

三要素:類名、屬性、方法

7.1.1 類的命名

  • 要有實際意義
  • 駝峰命名法——組成的單詞首字母大寫

    Dog、 CreditCard、 ElectricCar

# class 類名:
"""類前最好空兩行"""

class Car():
    """對該類的簡單介紹"""
    pass

"""類後最好也空兩行"""
           

7.1.2 類的屬性

class Car():
    """模拟汽車"""
    
    def __init__(self, brand, model, year):
        """初始化汽車屬性"""               # 相當于類内部的變量
        self.brand = brand                 # 汽車的品牌
        self.model = model                 # 汽車的型号
        self.year = year                   # 汽車出廠年份
        self.mileage = 0                   # 新車總裡程初始化為0        
           

7.1.3 類的方法

class Car():
    """模拟汽車"""
    
    def __init__(self, brand, model, year):
        """初始化汽車屬性"""               # 相當于類内部的變量
        self.brand = brand                 # 汽車的品牌
        self.model = model                 # 汽車的型号
        self.year = year                   # 汽車出廠年份
        self.mileage = 0                   # 新車總裡程初始化為0  
        
    def get_main_information(self):        # self不能省
        """擷取汽車主要資訊"""
        print("品牌:{}   型号:{}   出廠年份:{}".format(self.brand, self.model, self.year))
    
    def get_mileage(self):
        """擷取總裡程"""
        return "行車總裡程:{}公裡".format(self.mileage)
           
行車總裡程:0公裡
           

7.2 建立執行個體

7.2.1 執行個體的建立

将執行個體指派給對象,執行個體化過程中,傳入相應的參數

v = 類名(必要的初始化參數)

7.2.2 通路屬性

執行個體名.屬性名

print(my_new_car.brand)
print(my_new_car.model)
print(my_new_car.year)
           
Audi
A6
2018
           

7.2.3 調用方法

class Car():
    """模拟汽車"""
    
    def __init__(self, brand, model, year):
        """初始化汽車屬性"""               # 相當于類内部的變量
        self.brand = brand                 # 汽車的品牌
        self.model = model                 # 汽車的型号
        self.year = year                   # 汽車出廠年份
        self.mileage = 0                   # 新車總裡程初始化為0  
        
    def get_main_information(self):        # self不能省
        """擷取汽車主要資訊"""
        print("品牌:{}   型号:{}   出廠年份:{}".format(self.brand, self.model, self.year))
    
    def get_mileage(self):
        """擷取總裡程數"""
        return "行車總裡程:{}公裡".format(self.mileage)
           

執行個體名.方法名(必要的參數)

my_new_car = Car("Audi", "A6", 2018)
my_new_car.get_main_information()
           
品牌:Audi   型号:A6   出廠年份:2018
           
mileage = my_new_car.get_mileage()
print(mileage)
           
行車總裡程:0公裡
           

7.2.4 修改屬性

1、直接修改

先通路,後修改

print(my_old_car.mileage)
my_old_car.mileage = 12000
print(my_old_car.mileage)
           
0
12000
           
行車總裡程:12000公裡
           

2、通過方法修改屬性

class Car():
    """模拟汽車"""
    
    def __init__(self, brand, model, year):
        """初始化汽車屬性"""               # 相當于類内部的變量
        self.brand = brand                 # 汽車的品牌
        self.model = model                 # 汽車的型号
        self.year = year                   # 汽車出廠年份
        self.mileage = 0                   # 新車總裡程初始化為0  
        
    def get_main_information(self):        # self不能省
        """擷取汽車主要資訊"""
        print("品牌:{}   型号:{}   出廠年份:{}".format(self.brand, self.model, self.year))
    
    def get_mileage(self):
        """擷取總裡程數"""
        return "行車總裡程:{}公裡".format(self.mileage)
    
    def set_mileage(self, distance):
        """設定總裡程數"""
        self.mileage = distance
           
my_old_car = Car("BYD", "宋", 2016)
print(my_old_car.get_mileage())
my_old_car.set_mileage(8000)
print(my_old_car.get_mileage())
           
行車總裡程:0公裡
品牌:BYD   型号:宋   出廠年份:2016
行車總裡程:8000公裡
           

3、繼續拓展

  • 禁止設定負裡程
class Car():
    """模拟汽車"""
    
    def __init__(self, brand, model, year):
        """初始化汽車屬性"""               # 相當于類内部的變量
        self.brand = brand                 # 汽車的品牌
        self.model = model                 # 汽車的型号
        self.year = year                   # 汽車出廠年份
        self.mileage = 0                   # 新車總裡程初始化為0  
        
    def get_main_information(self):        # self不能省
        """擷取汽車主要資訊"""
        print("品牌:{}   型号:{}   出廠年份:{}".format(self.brand, self.model, self.year))
    
    def get_mileage(self):
        """擷取總裡程數"""
        print("行車總裡程:{}公裡".format(self.mileage)) 
    
    def set_mileage(self, distance):
        """設定總裡程數"""
        if distance >= 0:
            self.mileage = distance
        else:
            print("裡程數不能為負!")
    
    def increment_mileage(self, distance):
        """總裡程數累計"""
        if distance >= 0:
            self.mileage += distance
        else:
            print("新增裡程數不能為負!") 
            
           
my_old_car = Car("BYD", "宋", 2016)
my_old_car.get_mileage()
my_old_car.set_mileage(-8000)
my_old_car.get_mileage()
           
行車總裡程:0公裡
裡程數不能為負!
行車總裡程:0公裡
           
  • 将每次的裡程數累加
my_old_car.get_mileage()
my_old_car.set_mileage(8000)
my_old_car.get_mileage()
my_old_car.increment_mileage(500)
my_old_car.get_mileage()
           
行車總裡程:0公裡
行車總裡程:8000公裡
行車總裡程:8500公裡
           

小結

my_new_car = Car("Audi", "A6", 2018)
my_cars = [my_new_car, my_old_car]
           
  • 包含的資訊量可以是極大的,可以建立無窮多的執行個體
  • 高度的拟人(物)化,符合人類對客觀世界的抽象和了解

7.3 類的繼承

引子

看一下人在生物界的分支鍊

生物——動物界——脊索動物門——哺乳動物綱——靈長目——人科——人屬——智人種

公共特征逐漸增加的過程

【問題】

假設二進制系統: 人屬 = {A人種, B人種, C人種。。。。}

為每一個人種構造一個類

方案一:

各自獨立,分别構造各自人種的類

方案二:

1、将各人種公共特征提取出來,建立人屬的類;

2、各人種繼承上一級(人屬)的公共特征,然後添加自身特殊特征,建構各自人種的類。

通常,我們選擇方案二,因為這樣避免了過多的重複勞動

所謂繼承,就是低層抽象繼承高層抽象的過程

7.3.1 簡單的繼承

父類

class Car():
    """模拟汽車"""
    
    def __init__(self, brand, model, year):
        """初始化汽車屬性"""               # 相當于類内部的變量
        self.brand = brand                 # 汽車的品牌
        self.model = model                 # 汽車的型号
        self.year = year                   # 汽車出廠年份
        self.mileage = 0                   # 新車總裡程初始化為0
        
        
    def get_main_information(self):        # self不能省
        """擷取汽車主要資訊"""
        print("品牌:{}   型号:{}   出廠年份:{}".format(self.brand, self.model, self.year))
    
    def get_mileage(self):
        """擷取總裡程數"""
        print("行車總裡程:{}公裡".format(self.mileage)) 
    
    def set_mileage(self, distance):
        """設定總裡程數"""
        if distance >= 0:
            self.mileage = distance
        else:
            print("裡程數不能為負!")
    
    def increment_mileage(self, distance):
        """總裡程數累計"""
        if distance >= 0:
            self.mileage += distance
        else:
            print("新增裡程數不能為負!")
           

子類

class 子類名(父類名):

  • 建立一個電動汽車的類
class ElectricCar(Car):
    """模拟電動汽車"""
    
    def __init__(self, brand, model, year):
        """初始化電動汽車屬性"""
        super().__init__(brand, model,year)  # 聲明繼承父類的屬性
           
  • 自動繼承父類的所有方法
my_electric_car = ElectricCar("NextWeek", "FF91", 2046)
my_electric_car.get_main_information()
           
'品牌:NextWeek   型号:FF91   出廠年份:2046'
           

7.3.2 給子類添加屬性和方法

class ElectricCar(Car):
    """模拟電動汽車"""
    
    def __init__(self, brand, model, year, bettery_size):
        """初始化電動汽車屬性"""
        super().__init__(brand, model, year)    # 聲明繼承父類的屬性
        self.bettery_size = bettery_size        # 電池容量
        self.electric_quantity = bettery_size   # 電池剩餘電量
        self.electric2distance_ratio = 5        # 電量距離換算系數 5公裡/kW.h
        self.remainder_range = self.electric_quantity*self.electric2distance_ratio # 剩餘可行駛裡程
    
    def get_electric_quantit(self):
        """檢視目前電池電量"""
        print("目前電池剩餘電量:{} kW.h".format(self.electric_quantity))
        
    def set_electric_quantity(self, electric_quantity):
        """設定電池剩餘電量,重新計算電量可支撐行駛裡程"""
        if electric_quantity >= 0 and electric_quantity <= self.bettery_size:
            self.electric_quantity = electric_quantity
            self.remainder_range = self.electric_quantity*self.electric2distance_ratio
        else:
            print("電量未設定在合理範圍!")
    
    def get_remainder_range(self):
        """檢視剩餘可行駛裡程"""
        print("目前電量還可以繼續駕駛 {} 公裡".format(self.remainder_range))              
           
my_electric_car = ElectricCar("NextWeek", "FF91", 2046, 70)
my_electric_car.get_electric_quantit()            # 擷取目前電池電量
my_electric_car.get_remainder_range()             # 擷取目前剩餘可行駛裡程
           
目前電池剩餘電量:70 kW.h
目前電量還可以繼續駕駛 350 公裡
           
my_electric_car.set_electric_quantity(50)         # 重設電池電量
my_electric_car.get_electric_quantit()            # 擷取目前電池電量
my_electric_car.get_remainder_range()             # 擷取目前剩餘可行駛裡程
           
目前電池剩餘電量:50 kW.h
目前電量還可以繼續駕駛 250 公裡
           

7.3.3 重寫父類的方法——多态

class ElectricCar(Car):
    """模拟電動汽車"""
    
    def __init__(self, brand, model, year, bettery_size):
        """初始化電動汽車屬性"""
        super().__init__(brand, model, year)    # 聲明繼承父類的屬性
        self.bettery_size = bettery_size        # 電池容量
        self.electric_quantity = bettery_size   # 電池剩餘電量
        self.electric2distance_ratio = 5        # 電量距離換算系數 5公裡/kW.h
        self.remainder_range = self.electric_quantity*self.electric2distance_ratio # 剩餘可行駛裡程
    
    def get_main_information(self):        # 重寫父類方法
        """擷取汽車主要資訊"""
        print("品牌:{}   型号:{}   出廠年份:{}   續航裡程:{} 公裡"
              .format(self.brand, self.model, self.year, self.bettery_size*self.electric2distance_ratio))
    
    def get_electric_quantit(self):
        """檢視目前電池電量,重新計算電量可支撐行駛裡程"""
        print("目前電池剩餘電量:{} kW.h".format(self.electric_quantity))
        
    def set_electric_quantity(self, electric_quantity):
        """設定電池剩餘電量"""
        if electric_quantity >= 0 and electric_quantity <= self.bettery_size:
            self.electric_quantity = electric_quantity
            self.remainder_range = self.electric_quantity*self.electric2distance_ratio
        else:
            print("電量未設定在合理範圍!")
    
    def get_remainder_range(self):
        """檢視剩餘可行駛裡程"""
        print("目前電量還可以繼續駕駛 {} 公裡".format(self.remainder_range))
           
my_electric_car = ElectricCar("NextWeek", "FF91", 2046, 70)
my_electric_car.get_main_information()
           
品牌:NextWeek   型号:FF91   出廠年份:2046   續航裡程:350 公裡
           

7.3.4 用在類中的執行個體

把電池抽象成一個對象

邏輯更加清晰

class Bettery():
    """模拟電動汽車的電池"""
    
    def __init__(self, bettery_size = 70):
        self.bettery_size = bettery_size        # 電池容量
        self.electric_quantity = bettery_size   # 電池剩餘電量
        self.electric2distance_ratio = 5        # 電量距離換算系數 5公裡/kW.h
        self.remainder_range = self.electric_quantity*self.electric2distance_ratio # 剩餘可行駛裡程

    def get_electric_quantit(self):
        """檢視目前電池電量"""
        print("目前電池剩餘電量:{} kW.h".format(self.electric_quantity))
        
    def set_electric_quantity(self, electric_quantity):
        """設定電池剩餘電量,計重新算電量可支撐行駛裡程"""
        if electric_quantity >= 0 and electric_quantity <= self.bettery_size:
            self.electric_quantity = electric_quantity
            self.remainder_range = self.electric_quantity*self.electric2distance_ratio
        else:
            print("電量未設定在合理範圍!")
    
    def get_remainder_range(self):
        """檢視剩餘可行駛裡程"""
        print("目前電量還可以繼續駕駛 {} 公裡".format(self.remainder_range))
           
class ElectricCar(Car):
    """模拟電動汽車"""
    
    def __init__(self, brand, model, year, bettery_size):
        """初始化電動汽車屬性"""
        super().__init__(brand, model, year)    # 聲明繼承父類的屬性
        self.bettery = Bettery(bettery_size)    # 電池
    
    def get_main_information(self):        # 重寫父類方法
        """擷取汽車主要資訊"""
        print("品牌:{}   型号:{}   出廠年份:{}   續航裡程:{} 公裡"
              .format(self.brand, self.model, self.year, 
              self.bettery.bettery_size*self.bettery.electric2distance_ratio))
           
my_electric_car = ElectricCar("NextWeek", "FF91", 2046, 70)
my_electric_car.get_main_information()                  # 擷取車輛主要資訊
           
品牌:NextWeek   型号:FF91   出廠年份:2046   續航裡程:350 公裡
           
目前電池剩餘電量:70 kW.h
           
目前電池剩餘電量:50 kW.h
           
目前電量還可以繼續駕駛 250 公裡