Python?向對象的繼承指的是多個類之間的所屬關系,即?類默認繼承?類的所有屬性和?法。
繼承作用:繼承可以使用現有類的所有功能,并在無需重新編寫原來的類的情況下對這些功能進行擴展。
在Python中,所有類默認繼承object類,object類是頂級類或基類;其他?類叫做派?類。
class Being: # 定義一個類Beingdef __init__(self): #初始化實例屬性self.num = 1 #在類里面添加實例屬性self.屬性名=值def info_print(self): # 定義一個實例方法print(self.num) # 在類里面訪問實例屬性self.屬性名class People(Being): # 定義一個類People,繼承Being類passp1 = People() # 創建People類的一個對象p1
p1.info_print() # 對象調用父類實例方法
p1.num # 對象訪問父類實例屬性輸出:1
class Being(object):def __init__(self):self.num = 1def info_print(self):print(self.num)class People(Being):passp1 = People()
p1.info_print()輸出:1
單繼承:一個子類繼承一個父類
class Master:def __init__(self):self.kongfu = "古法配方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(Master):passdaqiu = prentice()
print(daqiu.kongfu)
daqiu.make_cake()輸出:
古法配方
古法配方制作煎餅果子
python子類繼承父類屬性。多繼承:一個子類同時繼承多個?類
當?個類有多個父類的時候,默認使用第?個父類的同名屬性和方法。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(Master, School):passdaqiu = prentice()
print(daqiu.kongfu) # 同名屬性,訪問第一個父類的同名屬性
daqiu.make_cake() # 同名方法,訪問第一個父類的同名方法print(daqiu.age) # 不同名屬性,第一個父類正常
print(daqiu.name) # 不同名屬性,非第一個父類報錯
輸出:
?類和父類具有同名屬性和方法,默認使用子類的同名屬性和方法。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "獨創配方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))daqiu = prentice()
print(daqiu.kongfu) # 同名屬性,重寫父類
daqiu.make_cake() # 同名方法,重寫父類
#如果子類和父類有同名屬性和方法,子類創建對象調用屬性和方法,調用的是子類里面的同名屬性和方法# print(daqiu.age) # 不同名屬性,報錯
print(daqiu.name) # 不同名屬性,報錯
輸出:
python多重繼承順序。Python的MRO即Method Resolution Order(方法解析順序),即在調用方法時,會對當前類以及所有的基類進行一個搜索,以確定該方法之所在,而這個搜索的順序就是MRO。
類名.__mro__,返回一個元組。
可以清晰地看到類的層級關系。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School(Master):def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(School):def __init__(self):self.kongfu = "獨創配方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))print(prentice.__mro__)
print(type(prentice.__mro__))
print(list(prentice.__mro__))輸出:
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
<class 'tuple'>
[<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>]
子類里如果有與父類同名的屬性方法,調用這個屬性方法,調用的是子類里面的,調用不到父類里面的屬性方法。
python GIL,如何實現同名屬性方法,既能調用子類里面的,也能調用父類里面的呢?
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "獨創配方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))def make_master_cake(self): # 調用父類方法,為保證調用到的也是父類的屬性,必須在調用方法前調用父類的初始化,類名.__init__(self)Master.__init__(self)Master.make_cake(self)def make_school_cake(self):School.__init__(self)School.make_cake(self)daqiu = prentice()
print(daqiu.kongfu)
daqiu.make_cake()
daqiu.make_master_cake()
daqiu.make_school_cake()print(prentice.__mro__)輸出:
獨創配方 # 返回的是子類屬性
獨創配方制作煎餅果子 # 調用的是子類方法
古法配方制作煎餅果子 # 調用到了父類Master的方法
學校技術制作煎餅果子 # 調用到了父類School的方法
(<class '__main__.prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "獨創配方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))def make_master_cake(self): # 調用父類方法,為保證調用到的也是父類的屬性,必須在調用方法前調用父類的初始化,類名.__init__(self)Master.__init__(self)Master.make_cake(self)def make_school_cake(self):School.__init__(self)School.make_cake(self)daqiu = prentice()
daqiu.make_master_cake()
daqiu.make_school_cake()
print(daqiu.kongfu)
daqiu.make_cake()
print(prentice.__mro__)輸出:
古法配方制作煎餅果子
學校技術制作煎餅果子
學校技術 # 如果先調用了父類的屬性和方法,父類屬性會覆蓋子類屬性
學校技術制作煎餅果子 # 如果先調用了父類的屬性和方法,父類屬性會覆蓋子類屬性
(<class '__main__.prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
代碼修正,
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "獨創配方"def make_cake(self):self.__init__() # 如果先調用了父類的屬性和方法,父類屬性會覆蓋子類屬性,故在調用子類方法前,先調用子類自己的初始化print("{}制作煎餅果子".format(self.kongfu))def make_master_cake(self): # 調用父類同名屬性方法,為保證調用到的也是父類的屬性,必須在調用方法前調用父類的初始化,類名.__init__(self)Master.__init__(self) # 父類類名.__init__(self),父類初始化調用一次,注意不要漏寫selfMaster.make_cake(self) # 父類類名.函數(self), 父類方法調用一次,注意不要漏寫selfdef make_school_cake(self):School.__init__(self)School.make_cake(self)daqiu = prentice()
daqiu.make_master_cake()
daqiu.make_school_cake()
print(daqiu.kongfu)
daqiu.make_cake()輸出:
古法配方制作煎餅果子
學校技術制作煎餅果子
學校技術 # 因為先調用父類,這里子類同名屬性仍然被父類屬性覆蓋
獨創配方制作煎餅果子
多層繼承:大于兩層的繼承
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "獨創配方"def make_cake(self):self.__init__() # 如果先調用了父類的屬性和方法,父類屬性會覆蓋子類屬性,故在調用子類方法前,先調用子類自己的初始化print("{}制作煎餅果子".format(self.kongfu))def make_master_cake(self): # 調用父類同名屬性方法,為保證調用到的也是父類的屬性,必須在調用方法前調用父類的初始化,類名.__init__(self)Master.__init__(self) # 父類初始化調用一次,注意不要漏寫selfMaster.make_cake(self) # 父類方法調用一次,注意不要漏寫selfdef make_school_cake(self):School.__init__(self)School.make_cake(self)class TuShun(prentice):passxiaoqiu = TuShun() # 說明子類可以繼承父類所有屬性和方法
xiaoqiu.make_cake() # 調用父類prentice方法
xiaoqiu.make_master_cake() # 調用父類prentice的父類方法
xiaoqiu.make_school_cake() # 調用父類prentice的父類方法
print(xiaoqiu.make_cake) # 前一步調用父類prentice的父類school類,school類初始化后,屬性是school類的屬性輸出:
獨創配方制作煎餅果子
古法配方制作煎餅果子
學校技術制作煎餅果子
print(TuShun.__mro__)輸出:
(<class '__main__.TuShun'>, <class '__main__.prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
方法一:在子類里定義一個函數,在里面初始化父類屬性、調用父類方法
?法?特點:代碼冗余;?類類名如果變化,這?代碼需要頻繁修改。如果有多個父類,代碼量重復增加。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School(Master):def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(School):def __init__(self):self.kongfu = "獨創配方"def make_cake(self):self.__init__() # 如果先調用了父類的屬性和方法,父類屬性會覆蓋子類屬性,故在調用子類方法前,先調用子類自己的初始化print("{}制作煎餅果子".format(self.kongfu))# def make_master_cake(self): # 調用父類同名屬性方法,為保證調用到的也是父類的屬性,必須在調用方法前調用父類的初始化,類名.__init__(self)# Master.__init__(self) # 父類初始化調用一次,注意不要漏寫self# Master.make_cake(self) # 父類方法調用一次,注意不要漏寫self## def make_school_cake(self):# School.__init__(self)# School.make_cake(self)# ?法?:代碼冗余;?類類名如果變化,這?代碼需要頻繁修改def make_old_cake(self):Master.__init__(self)Master.make_cake(self)School.__init__(self)School.make_cake(self)daqiu = prentice()
daqiu.make_old_cake() # 從輸出可以看到,兩個父類的同名方法都調用到了
daqiu.make_cake()
print(prentice.__mro__)輸出:
古法配方制作煎餅果子
學校技術制作煎餅果子
獨創配方制作煎餅果子
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
python3super用法?方法二:super()方法,帶參數寫法, super(當前類名, self).函數()
方法二特點:super里的類名是當前類名,自己可以控制,防止改了類名而未改super里的類名。缺點是仍然需要注意上下保持一致,而且如果有多個父類,需要在多個父類里加入super代碼。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School(Master):def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))# 方法二(一):super(當前類名,self).函數()super(School, self).__init__()super(School, self).make_cake()class prentice(School):def __init__(self):self.kongfu = "獨創配方"def make_cake(self):self.__init__() # 如果先調用了父類的屬性和方法,父類屬性會覆蓋子類屬性,故在調用子類方法前,先調用子類自己的初始化print("{}制作煎餅果子".format(self.kongfu))# def make_master_cake(self): # 調用父類同名屬性方法,為保證調用到的也是父類的屬性,必須在調用方法前調用父類的初始化,類名.__init__(self)# Master.__init__(self) # 父類初始化調用一次,注意不要漏寫self# Master.make_cake(self) # 父類方法調用一次,注意不要漏寫self## def make_school_cake(self):# School.__init__(self)# School.make_cake(self)# ?法?:代碼冗余;?類類名如果變化,這?代碼需要頻繁修改# def make_old_cake(self):# Master.__init__(self)# Master.make_cake(self)# School.__init__(self)# School.make_cake(self)# 方法二(一):super(當前類名,self).函數()def make_old_cake(self): # 需要同時在當前類prentice的父類School里也加super()super(prentice, self).__init__()super(prentice, self).make_cake()daqiu = prentice()
daqiu.make_old_cake()
daqiu.make_cake()
print(prentice.__mro__)輸出:
學校技術制作煎餅果子
古法配方制作煎餅果子
獨創配方制作煎餅果子
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
<推薦使用以下方法>
方法三:super()方法,無參數寫法, super().函數()
方法三特點:super()無參數寫法,自動查找直接父類
使?super() 可以?動查找?類。調?順序遵循 mro 類屬性的順序。?較適合單繼承使?。
.
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School(Master):def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))# 方法二(一):super(當前類名,self).函數()# super(School, self).__init__()# super(School, self).make_cake()# 方法二(二):super(當前類名,self).函數()super().__init__()super().make_cake()class prentice(School):def __init__(self):self.kongfu = "獨創配方"def make_cake(self):self.__init__() # 如果先調用了父類的屬性和方法,父類屬性會覆蓋子類屬性,故在調用子類方法前,先調用子類自己的初始化print("{}制作煎餅果子".format(self.kongfu))# def make_master_cake(self): # 調用父類同名屬性方法,為保證調用到的也是父類的屬性,必須在調用方法前調用父類的初始化,類名.__init__(self)# Master.__init__(self) # 父類初始化調用一次,注意不要漏寫self# Master.make_cake(self) # 父類方法調用一次,注意不要漏寫self## def make_school_cake(self):# School.__init__(self)# School.make_cake(self)# ?法?:代碼冗余;?類類名如果變化,這?代碼需要頻繁修改# def make_old_cake(self):# Master.__init__(self)# Master.make_cake(self)# School.__init__(self)# School.make_cake(self)# 方法二(一):super(當前類名,self).函數()# def make_old_cake(self): # 需要同時在當前類prentice的父類School里也加super()# super(prentice, self).__init__()# super(prentice, self).make_cake()# 方法二(二):super(當前類名,self).函數()def make_old_cake(self):super().__init__()super().make_cake()daqiu = prentice()
daqiu.make_old_cake()
daqiu.make_cake()
print(prentice.__mro__)輸出:
學校技術制作煎餅果子
古法配方制作煎餅果子
獨創配方制作煎餅果子
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
默認情況下,只要繼承關系建立,子類默認繼承父類所有的屬性和方法,這些能夠繼承給子類的屬性方法叫共有權限。
如果有些屬性和方法不想繼承給子類了,私有權限,可以添加私有屬性方法來實現。
注意:私有屬性和私有方法只能在類里面訪問和修改。,對某些屬性方法起到保護作用。
python拋出異常、.
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(School, Master):def __init__(self):self.kongfu = "獨創配方"self.__money = "一個億" # 定義私有屬性def __printinfo(self): # 定義私有?法print(self.kongfu)print(self.__money)def make_cake(self):self.__init__() # 如果先調用了父類的屬性和方法,父類屬性會覆蓋子類屬性,故在調用子類方法前,先調用子類自己的初始化print("{}制作煎餅果子".format(self.kongfu))class TuShun(prentice):passxiaoqiu = TuShun()
print(xiaoqiu.kongfu) # 獨創配方
print(xiaoqiu.money) # AttributeError: 'TuShun' object has no attribute 'money'
print(xiaoqiu.__money) # AttributeError: 'TuShun' object has no attribute '__money'
xiaoqiu.printinfo # AttributeError: 'TuShun' object has no attribute 'printinfo'
xiaoqiu.__printinfo # AttributeError: 'TuShun' object has no attribute '__printinfo'
# ?類?法繼承?類的私有屬性和私有?法
在Python中,在類里面,定義函數 get_屬性名 ?來獲取私有屬性,定義 set_屬性名 ?來修改私有屬性值。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "學校技術"self.name = "新東方"def make_cake(self):print("{}制作煎餅果子".format(self.kongfu))class prentice(School, Master):def __init__(self):self.kongfu = "獨創配方"self.__money = "私有:一個億"def get_money(self):print(self.__money) # 或者這里用 return self.__money,調用時用printdef set_money(self):self.__money = "私有更新:十個億"def __printinfo(self):print(self.kongfu)print(self.__money)def make_cake(self):self.__init__() # 如果先調用了父類的屬性和方法,父類屬性會覆蓋子類屬性,故在調用子類方法前,先調用子類自己的初始化print("{}制作煎餅果子".format(self.kongfu))class TuShun(prentice):passxiaoqiu = TuShun()
xiaoqiu.get_money()
xiaoqiu.set_money()
xiaoqiu.get_money()print(prentice.__mro__)輸出:
私有:一個億
私有更新:十個億
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
class Dog:__age = 3@classmethoddef get_age(cls):return cls.__agewangcai = Dog()
result = wangcai.get_age()
print(result) # 3
PS: source,itheima
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态