技術交流QQ群:1027579432,歡迎你的加入胞谈!
1.封裝
- 封裝:將數(shù)據(jù)與具體操作的實現(xiàn)代碼放在某個對象內(nèi)部尘盼,使這些代碼的實現(xiàn)細節(jié)不被外界發(fā)現(xiàn)憨愉,外界只能通過接口使用該對象,而不能通過任何形式修改對象內(nèi)部實現(xiàn)卿捎,正是由于封裝機制配紫,程序在使用某一對象時不需要關心該對象的數(shù)據(jù)結(jié)構(gòu)細節(jié)及實現(xiàn)操作的方法。使用封裝能隱藏對象實現(xiàn)細節(jié)午阵,使代碼更易維護躺孝,同時因為不能直接調(diào)用、修改對象內(nèi)部的私有信息底桂,在一定程度上保證了系統(tǒng)安全性植袍。類通過將函數(shù)和變量封裝在內(nèi)部,實現(xiàn)了比函數(shù)更高一級的封裝籽懦。
class Student:
def __init__(self,name, age):
self.name = name
self.age = age
def printInfo(self):
print("name:{}".format(self.name), "age:{}".format(self.age))
# 下面的操作都是錯誤的于个!原因:類將它內(nèi)部的變量和方法封裝起來,阻止外部的直接訪問
print(name)
print(age)
printInfo()
2.繼承
- 繼承:定義一個新類的時候猫十,新的類稱為子類(Subclass)览濒,而被繼承的類稱為基類、父類或超類(Base class拖云、Super class)。繼承最大的好處是子類獲得了父類的全部變量和方法的同時应又,又可以根據(jù)需要進行修改宙项、擴展。其語法結(jié)構(gòu)如下:
class Foo(superA, superB,.... ):
class DerivedName(modelname.BaseName):
- Python支持多父類的繼承機制株扛,所以需要注意圓括號中基類的順序尤筐,若是基類中有相同的方法名,并且在子類使用時未指定洞就,Python會從左至右搜索基類中是否包含該方法盆繁,一旦查找到則直接調(diào)用,后面不再繼續(xù)查找旬蟋。
# 父類定義
class people:
def __init__(self, name, age, weight):
self.name = name
self.age = age
self.__weight = weight
def speak(self):
print("%s 說: 我 %d 歲油昂。" % (self.name, self.age))
# 單繼承示例
class student(people):
def __init__(self, name, age, weight, grade):
# 調(diào)用父類的實例化方法
people.__init__(self, name, age, weight)
self.grade = grade
# 重寫父類的speak方法
def speak(self):
print("%s 說: 我 %d 歲了,我在讀 %d 年級" % (self.name, self.age, self.grade))
s = student('ken', 10, 30, 3)
s.speak()
- Python3中的繼承原則倾贰,必須記憶:
-
原則1:子類在調(diào)用某個方法或變量的時候冕碟,首先在自己內(nèi)部查找,如果沒有找到匆浙,則開始根據(jù)繼承機制在父類里查找安寺。
class D: pass class C(D): pass class B(C): def show(self): print("i am B") pass class G: pass class F(G): pass class E(F): def show(self): print("i am E") pass class A(B, E): pass a = A() a.show()
- 解釋:運行結(jié)果是"i am B"。在類A中首尼,沒有show()這個方法挑庶,于是它只能去它的父類里查找言秸,它首先在B類中找,結(jié)果找到了迎捺,于是直接執(zhí)行B類的show()方法井仰。可見破加,在A的定義中俱恶,繼承參數(shù)的書寫有先后順序,寫在前面的被優(yōu)先繼承范舀。
-
原則2:根據(jù)父類定義中的順序合是,以深度優(yōu)先搜索(BFS)的方式逐一查找父類!
- 情況1:如果B沒有show方法锭环,而是D有呢聪全?
class D: def show(self): print("i am D") pass class C(D): pass class B(C): pass class G: pass class F(G): pass class E(F): def show(self): print("i am E") pass class A(B, E): pass a = A() a.show()
-
解釋:執(zhí)行結(jié)果是"i am D",左邊具有深度優(yōu)先權(quán)辅辩,當一條路走到黑也沒找到的時候难礼,才換另一條路∶捣妫可見蛾茉,在這種繼承結(jié)構(gòu)關系中,搜索順序是這樣的:
-
情況2:如果繼承結(jié)構(gòu)是這樣的呢撩鹿?谦炬,如下圖所示。類D和類G又同時繼承了類H节沦。當只有B和E有show方法的時候键思,無疑和上面的例子一樣,找到B就不找了甫贯,直接打印"i am B"吼鳞。但如果是只有H和E有show方法呢?
class H: def show(self): print("i am H") pass class D(H): pass class C(D): pass class B(C): pass class G(H): pass class F(G): pass class E(F): def show(self): print("i am E") pass class A(B, E): pass a = A() a.show()
-
解釋:在這種情況下叫搁,打印的是"i am E"赔桌,Python的搜索路徑是這樣的:
-
情況3:對于其他繼承情況,可以拆分成上面兩個情況常熙,如下圖所示:
class D(): pass class G(): def show(self): print("i am G") pass class F(G): pass class C(D): pass class B(C,F): pass class E(F): def show(self): print("i am E") pass class A(B, E): pass
-
- super()函數(shù):在子類中如果有與父類同名的成員纬乍,那就會覆蓋掉父類里的成員。那如果想強制調(diào)用父類的成員呢裸卫?使用super()函數(shù)仿贬!這是一個非常重要的函數(shù),最常見的就是通過super調(diào)用父類的實例化方法__init__墓贿!使用方法super(子類名,self).方法名()茧泪,需要傳入的是子類名和self蜓氨,調(diào)用的是父類里的方法,按父類的方法需要傳入?yún)?shù)队伟。
class A: def __init__(self, name): self.name = name print("父類的__init__方法被執(zhí)行了穴吹!") def show(self): print("父類的show方法被執(zhí)行了!") class B(A): def __init__(self, name, age): super(B, self).__init__(name=name) self.age = age def show(self): super(B, self).show() obj = B("jack", 18) obj.show()
3.多態(tài)
class Animal:
def kind(self):
print("i am animal")
class Dog(Animal):
def kind(self):
print("i am a dog")
class Cat(Animal):
def kind(self):
print("i am a cat")
class Pig(Animal):
def kind(self):
print("i am a pig")
# 這個函數(shù)接收一個animal參數(shù)嗜侮,并調(diào)用它的kind方法
def show_kind(animal):
animal.kind()
d = Dog()
c = Cat()
p = Pig()
show_kind(d)
show_kind(c)
show_kind(p)
- 狗港令、貓、豬都繼承了動物類锈颗,并各自重寫了kind方法顷霹。show_kind()函數(shù)接收一個animal參數(shù),并調(diào)用它的kind方法击吱×艿恚可以看出,無論我們給animal傳遞的是狗覆醇、貓還是豬朵纷,都能正確的調(diào)用相應的方法,打印對應的信息永脓,這就是多態(tài)袍辞。
- 由于Python的動態(tài)語言特性,傳遞給函數(shù)show_kind()的參數(shù)animal可以是任何的類型憨奸,只要它有一個kind()的方法即可革屠。動態(tài)語言調(diào)用實例方法時不檢查類型,只要方法存在排宰,參數(shù)正確,就可以調(diào)用那婉。這就是動態(tài)語言的“鴨子類型”板甘,它并不要求嚴格的繼承體系,一個對象只要“看起來像鴨子详炬,走起路來像鴨子”盐类,那它就可以被看做是鴨子。
class Job:
def kind(self):
print("i am not animal, i am a job")
j = Job()
show_kind(j)