網站首頁 編程語言 正文
繼承
編寫類時,并非總是要從空白開始,如果編寫的類是另一個現成類的特殊版本,可使用繼承,繼承分為單繼承和多繼承。
一個類繼承另一個類時,將自動獲得另一個類的所有屬性和方法,原有的類稱為父類,而新類稱為子類。子類繼承了父類所有的屬性和方法,同時還可以定義自己的屬性和方法,這樣一來就解決了類類與類之間代碼冗余的問題
那么兒子怎么查看自己的父親是誰呢?
如下所示:
class Parent_1:
pass
class Parent_2:
pass
class sub1(Parent_1):#單繼承
pass
#查看自己的父類
print(sub1.__bases__)
class sub2(Parent_1,Parent_2):#多繼承
pass
#查看自己的父類
print(sub2.__bases__)
(<class '__main__.Parent1'>,)
(<class '__main__.Parent1'>, <class '__main__.Parent2'>)
多繼承的優缺點
優點:子類可以同時遺傳多個父類的屬性,最大限度地重用代碼 缺點:違背倫理道德,一個兒子可以有多個爹,體現在程序中則為代碼地可讀性變差。
繼承查找的順序:
對象>子類>父類>父父類
舉例:
class Fu():
def f1(self):
print('Fu.f1')
def f2(self):
print('Fu.f2')
self.f1()#對象名.方法(),此時的self==objects
class son(Fu):
def f1(self):
print('son.f1')
objects=son()
objects.f2()
根據繼承查找的順序,對象>子類>父類>父父類,先在objects空間范圍內查找f2,如果未找到,再去子類空間范圍內查找,最后再去父類空間范圍內查找。
Foo.f2
Bar.f1
子類的方法__init__()
在既有類的基礎上編寫新類的時候,通常要調用父類的方法__init__(),這將初始化再父類__init__()方法中定義的所有屬性,從而讓子類包含這些屬性。
舉例:
#定義一個父類Car,父類又名超類,名稱super由此而來
class Car:
def __init__(self,make,model,year):
self.make=make
self.model=model
self.year=year
self.odometer_reading=0
def get_descriptive_name(self):
long_name=f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"this car has {self.odometer_reading} miles on it ")
def update_odometer(self,mileage):
if mileage>=self.odometer_reading:
self.odometer_reading=mileage
else:
print("you can't roll back an odometer!")
def increment_odometer(self,miles):
self.odometer_reading+=miles
#定義一個子類ELectricCar,創建子類時,父類必須包含在當前的文件,父類必須位于子類的前面
class ELectricCar(Car):#定義子類時,必須在圓括號內指定父類的名稱
#方法__init__()接受創建Car實例所需的信息
def __init__(self,make,model,year):
print("__init__()方法被調用")
#讓python調用Car類的方法__init__(),讓子類創建的實例包含父類這個方法中定義的所有屬性
super().__init__(make,model,year)#super是一個特殊函數,使我們能夠調用父類的方法
my_tesla=ELectricCar('tesla','model s',2019)
print(my_tesla.make)
print(my_tesla.year)
print(my_tesla.model)
print(my_tesla.get_descriptive_name())
__init__()方法被調用
tesla
2019
model s
2019 Tesla Model S
對于上述代碼,我們只是想查看子類ELectricCar是否繼承了父類Car所擁有的屬性,但是子類本身,我們并沒有給他設置自身屬性和方法。
給子類定義屬性和方法:
讓一個類繼承另一個類后,就可以添加區分子類和父類所需的新屬性和新方法了。
下面來添加一個電動車特有的屬性,以及描述該屬性的方法:
依然選用上面的代碼:
#定義一個父類Car,父類又名超類,名稱super由此而來
class Car:
def __init__(self,make,model,year):
self.make=make
self.model=model
self.year=year
self.odometer_reading=0
def get_descriptive_name(self):
long_name=f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"this car has {self.odometer_reading} miles on it ")
def update_odometer(self,mileage):
if mileage>=self.odometer_reading:
self.odometer_reading=mileage
else:
print("you can't roll back an odometer!")
def increment_odometer(self,miles):
self.odometer_reading+=miles
#定義一個子類ELectricCar,創建子類時,父類必須包含在當前的文件,父類必須位于子類的前面
class ELectricCar(Car):#定義子類時,必須在圓括號內指定父類的名稱
#方法__init__()接受創建Car實例所需的信息
def __init__(self,make,model,year):
print("__init__()方法被調用")
#讓python調用Car類的方法__init__(),讓子類創建的實例包含父類這個方法中定義的所有屬性
super().__init__(make,model,year)#super是一個特殊函數,使我們能夠調用父類的方法
self.battery_size=75
def describle_battery(self):
print(f"this car a {self.battery_size}-kwl battery")
my_tesla=ELectricCar('tesla','model s',2019)
print(my_tesla.get_descriptive_name())
my_tesla.describle_battery()
這時,我們給子類添加了它的專有屬性describle_battery_size:
#__init__()方法被調用
2019 Tesla Model S
this car a 75-kwl battery
下面我們主要對新添加的子類專有屬性進行分析:
def __init__(self,make,model,year):
print("__init__()方法被調用")
#讓python調用Car類的方法__init__(),讓子類創建的實例包含父類這個方法中定義的所有屬性
super().__init__(make,model,year)#super是一個特殊函數,使我們能夠調用父類的方法
self.battery_size=75
def describle_battery(self):#關于子類ELectricCar特有的描述
print(f"this car a {self.battery_size}-kwl battery")
self.battery_size=75為子類特有屬性,因此寫在子類的__init__()方法后,根據子類ELectricCar創建的所有實例都將把包含該屬性,但所有的Car實例都不包含它。
對于子類的特殊程度沒有任何限制,模擬子類ELectricCar時,可根據所需的準確程度添加任意數量的屬性和方法。
如果一個屬性或方法是任何汽車都有的,而不是子類ELectricCar特有的,就將應將其加入到父類Car中,而不是加入到子類ELectricCar中,這樣,使用父類Car類的人將獲得相應的功能,而使用子類ELectricCar的人只能獲得子類特有的屬性。
重寫父類的方法
對于父類的方法,只要他不符合子類模擬的實物的行為,都可以進行重寫,為此。可在子類中定義一個與要重寫的父類方法同名的方法,這樣,python將不會考慮這個父類方法,而只關注你在子類中定義的相應方法。
舉例:
假設父類Car有一個名為fill__gas__tank()的方法,他對于子類ELectricCar來說毫無意義,因此你可能想重寫它,那該怎么重寫呢?
可在子類中定義一個與要重寫的父類方法同名的方法
class Car:
---snip:
def fill_gas_tank(self):
self.fill_gas_tank=90
print(f"電瓶車郵箱尺寸的大小是{self.fill_gas_tank}")
class ELectricCar(Car):
--snip:
def fill_gas_tank(self):#與父類中該屬性的方法名相同
print("this car doesn't need a gas tank!")
my_tesla=ELectricCar('tesla','model s',2019)
print(my_tesla.get_descriptive_name())
my_tesla.fill_gas_tank()
將父類改寫之后,輸出的不符合子類ELectricCar的方法的相關行為是我們改寫后的,如果不進行改寫,那么則會輸出不相關的屬性行為。
#__init__()方法被調用
2019 Tesla Model S
this car doesn't need a gas tank!
將實例用作屬性
使用代碼模擬實物時,你可能會發現自己給類添加的細節越來越多:屬性和方法清單以及文件都越來越長,在這種情況下,可能需要將類的一部分提取出來,作為一個單獨的類,可以將大型類拆分成多個協同工作的小類。
例如,不斷給子類ELectricCar添加細節時,我們可能發現其中包含很多專門針對汽車電池的屬性和方法,在這種情況下我們可以將這些屬性和方法提取出來,放在一個名為battery的類中,并將一個battery實例作為子類ELectricCar的屬性:
舉例:
class Car:
--snip--
class Battery:#這里是重寫一個類
def __init__(self,battery_size=10):#該默認值可設定也可不設定
self.battery_size=battery_size
def describle_battery(self):
print(f"this car has a {self.battery_size}-kwl battery")
class ELectricCar(Car):
def __init__(self,make,model,year):
super().__init__(make,model,year)
self.battery=Battery()#在子類ELectricCar新添加了一個名為battery的屬性
#讓python創建一個新的Battery實例,并將該實例賦給屬性新創建的屬性battery
my_tesla=ELectricCar('tesla','model s',2019)
#和上面描述電池容量是一樣的方法
my_tesla.battery.describle_battery()#讓python在實例my_tasla中查找屬性battery,并對battery進行調用
下面我們再向Battery類中添加一個方法用來描述電瓶車的航行距離:
class Car:
--snip--
class Battery:
--snip--
def get_range(self):
if self.battery_size==75:
range = 260
elif self.battery_size==100:
range = 315
print(f"this car can go about {range} miles on a full charge")
class ELectricCar(Car):
--snip--
my_tesla=ELectricCar('tesla','model s',2019)
my_tesla.battery.describle_battery()
my_tesla.battery.get_range()#在my_tesla實例中查找battery,self.battery=Battery(),對Battery進行調用
#__init__被調用
this car has a 75-kwl battery
this car can go about 260 miles on a full charge
原文鏈接:https://blog.csdn.net/m0_64365419/article/details/125868241
相關推薦
- 2023-03-22 tkinter如何實現打開文件對話框并獲取文件絕對路徑_python
- 2022-07-17 絕對、相對導入以及包和常見內置模塊
- 2023-04-07 C++11學習之多線程的支持詳解_C 語言
- 2022-04-12 error: failed to push some refs to 'git@gitlab.xxx
- 2022-08-30 Window環境下配置Mongodb數據庫_MongoDB
- 2023-06-02 關于pip安裝opencv-python遇到的問題_python
- 2022-09-03 Python?Pandas中DataFrame.drop_duplicates()刪除重復值詳解_p
- 2022-06-24 C#利用itext實現PDF頁面處理與切分_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支