淺談Python類的單繼承相關(guān)知識(shí)
上文我們總結(jié)過了Python多繼承的相關(guān)知識(shí),沒看過的小伙伴們也可以去看看,今天給大家介紹Python類的單繼承相關(guān)知識(shí)。
一、類的繼承
面向?qū)ο笕刂?,繼承Inheritance
人類和貓類都繼承自動(dòng)物類。
個(gè)體繼承自父母,繼承了父母的一部分特征,但也可以有自己的個(gè)性。
在面向?qū)ο蟮氖澜缰?,從父類繼承,就可以直接擁有父類的屬性和方法,這樣就可以減少代碼、多服用。子類可以定義自己的屬性和方法
class Animal: def __init__(self,name): self._name = name def shout(self): print("{} shouts".format(self.__class__.__name__)) @property def name(self): return self._name class Cat(Animal): pass class Dog(Animal): pass a = Animal("monster") a.shout() # Animal shouts cat = Cat("garfield") cat.shout() # Cat shouts print(cat.name) # garfield dog = Dog("ahuang") dog.shout() # Dog shouts print(dog.name) # ahuang
上例中我們可以看出,通過繼承、貓類、狗類不用寫代碼,直接繼承了父類的屬性和方法
繼承:
- class Cat(Animal)這種形式就是從父類繼承,括號(hào)中寫上繼承的類的列表。
- 繼承可以讓子類重父類獲取特征(屬性、方法)
父類:
- Animal就是Cat的父類,也稱為基類、超類
子類:
- Cat 就是Animal的子類,也成為派生類
二、繼承的定義、查看繼承的特殊屬性和方法
格式
class 子類 (基類1[,基類2,……]): 語句塊
如果類定義時(shí),沒有基類列表,等同于繼承自【object】。在Python3中,【object】類是所有對(duì)象基類
查看繼承的特殊屬性和方法
特殊屬性 | 含義 | 示例 |
__base__ | 類的基類 |
|
__bases__ | 類的基類元組 | |
__mro__ | 顯示方法查找順序,基類的元組 | |
mro() | 同上 | int.mro() |
__subclasses__() | 類的子類列表 | int.__subclasses__() |
三、繼承中的訪問控制
class Animal: __COUNT = 100 HEIGHT = 0 def __init__(self,age,weight,height): self.__COUNT += 1 self.age = age self.__weight = weight self.HEIGHT = height def eat(self): print("{} eat".format(self.__class__.__name__)) def __getweight(self): print(self.__weight) @classmethod def showcount1(cls): print(cls.__COUNT) @classmethod def __showcount2(cls): print(cls.__COUNT) def showcount3(self): print(self.__COUNT) class Cat(Animal): NAME = "CAT" __COUNT = 200 #a = Cat() # TypeError: __init__() missing 3 required positional arguments: 'age', 'weight', and 'height' a = Cat(30,50,15) a.eat() # Cat eat print(a.HEIGHT) # 15 #print(a.__COUNT) # AttributeError: 'Cat' object has no attribute '__COUNT' #print(a.__showcount2) # AttributeError: 'Cat' object has no attribute '__showcount2' #print(a.__getweight) # AttributeError: 'Cat' object has no attribute '__getweight' a.showcount3() # 101 a.showcount1() # 100 print(a.NAME) # CAT print(Animal.__dict__) # {'__module__': '__main__', '_Animal__COUNT': 100, 'HEIGHT': 0, '__init__': <function Animal.__init__ at 0x020DC228>, 'eat': <function Animal.eat at 0x020DC468>, '_Animal__getweight': <function Animal.__getweight at 0x02126150>, 'showcount1': <classmethod object at 0x020E1BD0>, '_Animal__showcount2': <classmethod object at 0x020E1890>, 'showcount3': <function Animal.showcount3 at 0x021264F8>, '__dict__': <attribute '__dict__' of 'Animal' objects>, '__weakref__': <attribute '__weakref__' of 'Animal' objects>, '__doc__': None} print(Cat.__dict__) # {'__module__': '__main__', 'NAME': 'CAT', '_Cat__COUNT': 200, '__doc__': None} print(a.__dict__) # {'_Animal__COUNT': 101, 'age': 30, '_Animal__weight': 50, 'HEIGHT': 15}
從父類繼承、自己沒有的,就可以到父類中找
私有的都是不可訪問的,但是本質(zhì)上依然是改了名稱放在這個(gè)屬性所在的類的了【__dict__】中,知道這個(gè)新民成就可以了直接找到這個(gè)隱藏的變量,這是個(gè)黑魔法慎用
總結(jié)
- 繼承時(shí),共有的,子類和實(shí)例都可以隨意訪問;私有成員被隱藏,子類和實(shí)例不可直接訪問,當(dāng)私有變量所在類內(nèi)方法中可以訪問這個(gè)私有變量
- Python通過自己一套實(shí)現(xiàn),實(shí)現(xiàn)和其他語言一樣的面向?qū)ο蟮睦^承機(jī)制
屬性查找順序:實(shí)例的【__dict__】------類的【__dict__】-----父類【__dict__】
如果搜索這些地方后沒有找到異常,先找到就立即返回
四、方法的重寫、覆蓋override
class Animal: def shout(self): print("Animal shouts") class Cat(Animal): def shout(self): print("miao") a = Animal() a.shout() # Animal shouts b = Cat() b.shout() # miao print(a.__dict__) # {} print(b.__dict__) # {} print(Animal.__dict__) # {'__module__': '__main__', 'shout': <function Animal.shout at 0x017BC228>, '__dict__': <attribute '__dict__' of 'Animal' objects>, '__weakref__': <attribute '__weakref__' of 'Animal' objects>, '__doc__': None}
Cat類中shout為什么沒有打印Animal中shout的方法,方法被覆蓋了?
- 這是因?yàn)椋?strong>屬性查找順序:實(shí)例的【__dict__】------類的【__dict__】-----父類【__dict__】
那子類如何打印父類的同命的方法
- super()可以訪問到父類的屬性
class Animal: def shout(self): print("Animal shouts") class Cat(Animal): def shout(self): print("miao") def shout(self): print("super(): " , super()) print(super(Cat, self)) super().shout() super(Cat,self).shout() # 等價(jià)于super().shout() self.__class__.__base__.shout(self) #不推薦使用 a = Animal() a.shout() # Animal shouts b = Cat() b.shout() # super(): <super: <class 'Cat'>, <Cat object>> # <super: <class 'Cat'>, <Cat object>> # Animal shouts # Animal shouts # Animal shouts print(a.__dict__) # {} print(b.__dict__) # {} print(Animal.__dict__) # {'__module__': '__main__', 'shout': <function Animal.shout at 0x019AC228>, '__dict__': <attribute '__dict__' of 'Animal' objects>, '__weakref__': <attribute '__weakref__' of 'Animal' objects>, '__doc__': None} print(Cat.__dict__) # {'__module__': '__main__', 'shout': <function Cat.shout at 0x019F6150>, '__doc__': None}
super(Cat,self).shout()的作用相當(dāng)于
- 調(diào)用,當(dāng)前b的實(shí)例中找cat類的基類中,shout的方法
那對(duì)于類方法和靜態(tài)方法是否也同樣適用尼?
class Animal: @classmethod def class_method(cls): print("class_method") @staticmethod def static_method(): print("static_methond_animal") class Cat(Animal): @classmethod def class_method(cls): super().class_method() # class_method print("class_method_cat") @staticmethod def static_method(cls,self): super(Cat,self).static_method() print("static_method_cat") b = Cat() b.class_method() # class_method # class_method_cat b.static_method(Cat,b) # static_methond_animal # static_method_cat
這些方法都可以覆蓋,原理都一樣,屬性字典的搜索順序
五、繼承中的初始化
看以下一段代碼,有沒有問題
class A: def __init__(self,a): self.a = a class B(A): def __init__(self,b,c): self.b = b self.c = c def printv(self): print(self.b) print(self.a) a = B(100,300) print(a.__dict__) # {'b': 100, 'c': 300} print(a.__class__.__bases__) # (<class '__main__.A'>,) a.printv() # 100 # AttributeError: 'B' object has no attribute 'a'
上例代碼
- 如果B類定義時(shí)聲明繼承自類A,則在B類中__bases__中是可以看到類A
- 這和是否調(diào)用類A的構(gòu)造方法是兩回事
- 如果B中調(diào)用了A的構(gòu)造方法,就可以擁有父類的屬性了,如果理解這一句話?
class A: def __init__(self,a): self.a = a class B(A): def __init__(self,b,c): super().__init__(b+c) # A.__init__(self,b+c) self.b = b self.c = c def printv(self): print(self.b) print(self.a) a = B(100,300) print(a.__dict__) # {'a': 400, 'b': 100, 'c': 300} print(a.__class__.__bases__) # (<class '__main__.A'>,) a.printv() # 100 # 400
作為好的習(xí)慣,如果父類定義了__init__方法,你就改在子類__init__中調(diào)用它【建議適用super()方法調(diào)用】
那子類什么時(shí)候自動(dòng)調(diào)用父類的【__init__】方法?
例子一:【B實(shí)例的初始化會(huì)自動(dòng)調(diào)用基類A的__init__方法】
class A: def __init__(self): self.a1 = "a1" self.__a2 = "a2" print("A init") class B(A): pass b = B() # A init print(b.__dict__) # {'a1': 'a1', '_A__a2': 'a2'}
例子二:【B實(shí)例的初始化__init__方法不會(huì)自動(dòng)調(diào)用父類的初始化__init__方法,需要手動(dòng)調(diào)用】
class A: def __init__(self): self.a1 = "a1" self.__a2 = "a2" print("A init") class B(A): def __init__(self): self.b1 = "b1" self.__b2 = "b2" print("b init") #A.__init__(self) b = B() # b init print(b.__dict__) # {'b1': 'b1', '_B__b2': 'b2'}
那如何正確實(shí)例化?
- 注意,調(diào)用父類的__init__方法,出現(xiàn)在不同的位置,可能導(dǎo)致出現(xiàn)不同的結(jié)果
class Animal: def __init__(self,age): print("Animal init") self.age = age def show(self): print(self.age) class Cat(Animal): def __init__(self,age,weight): #調(diào)用父類的__init__方法的順序 決定show方法的結(jié)果 super(Cat, self).__init__(age) print("Cat init") self.age = age + 1 self.weight = weight a = Cat(10,5) a.show() # Animal init # Cat init # 11
怎么直接將上例中所有的實(shí)例屬性改變?yōu)樗接袑傩裕?/p>
- 解決辦法,一個(gè)原則,自己的私有屬性,就該自己的方法讀取和修改,不要借助其他類的方法,即父類或者派生類
class Animal: def __init__(self,age): print("Animal init") self.__age = age def show(self): print(self.__age) class Cat(Animal): def __init__(self,age,weight): #調(diào)用父類的__init__方法的順序 決定show方法的結(jié)果 super(Cat, self).__init__(age) print("Cat init") self.__age = age + 1 self.__weight = weight def show(self): print(self.__age) a = Cat(10,5) a.show() # Animal init # Cat init # 11 print(a.__dict__) # {'_Animal__age': 10, '_Cat__age': 11, '_Cat__weight': 5}
到此這篇關(guān)于淺談Python類的單繼承相關(guān)知識(shí)的文章就介紹到這了,更多相關(guān)Python類的單繼承內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何將DataFrame數(shù)據(jù)寫入csv文件及讀取
在Python中進(jìn)行數(shù)據(jù)處理時(shí),經(jīng)常會(huì)用到CSV文件的讀寫操作,當(dāng)需要將list數(shù)據(jù)保存到CSV文件時(shí),可以使用內(nèi)置的csv模塊,若data是一個(gè)list,saveData函數(shù)能夠?qū)ist中每個(gè)元素存儲(chǔ)在CSV文件的一行,但需要注意的是,默認(rèn)情況下讀取出的CSV數(shù)據(jù)類型為str2024-09-09深入分析python數(shù)據(jù)挖掘 Json結(jié)構(gòu)分析
這篇文章通過實(shí)例給大家分析總結(jié)了python數(shù)據(jù)挖掘以及Json結(jié)構(gòu)分析的相關(guān)知識(shí)點(diǎn),對(duì)此有興趣的朋友參考下。2018-04-04如何用Anaconda搭建虛擬環(huán)境并創(chuàng)建Django項(xiàng)目
在本篇文章里小編給大家整理了關(guān)于如何用Anaconda搭建虛擬環(huán)境并創(chuàng)建Django項(xiàng)目的相關(guān)文章,需要的朋友們可以跟著學(xué)習(xí)下。2020-08-08Python 圖片文字識(shí)別的實(shí)現(xiàn)之PaddleOCR
OCR方向的工程師,之前一定聽說過PaddleOCR這個(gè)項(xiàng)目,其主要推薦的PP-OCR算法更是被國(guó)內(nèi)外企業(yè)開發(fā)者廣泛應(yīng)用,短短半年時(shí)間,累計(jì)Star數(shù)量已超過15k,頻頻登上Github Trending和Paperswithcode 日榜月榜第一2021-11-11