第七章 類——面向對象的編程
引子
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 類的屬性
# def __init__(self,要傳遞的參數) 初始化類的屬性
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)
My_Car = Car("Audi","sb",2019)
print(My_Car.get_mileage())
行車總里程:0公里
7.2 創建實例
7.2.1 實例的創建
將實例賦值給對象,實例化過程中,傳入相應的參數
v = 類名(必要的初始化參數)
my_new_car = Car("Audi", "A6", 2018)
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、直接修改
my_old_car = Car("BYD", "宋", 2016)
先訪問,後修改
print(my_old_car.mileage)
my_old_car.mileage = 12000
print(my_old_car.mileage)
0
12000
print(my_old_car.get_mileage())
行車總里程: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) # 聲明繼承父類的屬性
A = ElectricCar("au","23",90)
- 自動繼承父類的所有方法
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 公里
my_electric_car.bettery.get_electric_quantit() # 獲取當前電池電量
當前電池剩餘電量:70 kW.h
my_electric_car.bettery.set_electric_quantity(50) # 重設電池電量
my_electric_car.bettery.get_electric_quantit() # 獲取當前電池電量
當前電池剩餘電量:50 kW.h
my_electric_car.bettery.get_remainder_range() # 獲取當前剩餘可行駛里程
當前電量還可以繼續駕駛 250 公里