目錄
1:繼承與多態介紹
繼承:主要用於複用以前的代碼,縮短開發週期。
繼承就是子類繼承父類的特徵和行爲,使得子類對象(實例)具有父類的屬性和方法,或子類從父類繼承方法,使得子類具有父類相同的行爲。
多態:同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果。
把不同的子類對象都當作父類來看,可以屏蔽不同子類對象之間的差異,寫出通用的代碼,做出通用的編程,以適應需求的不斷變化。
2:繼承與多態示例代碼
# encoding=gbk
class Animal:
AnimalType = 'Animal' # 是類屬性
def __init__(self,name='Animal'):
self.name = name
def showInfo(self): # self 是具體的實例對象,type(self) 返回self對應的類(Animal或Animal的子類),
print('類型:' + type(self).AnimalType + ' 名稱:' + self.name)
def eat(self):
print('in Animal-喫喫喫!')
class Dog(Animal): # 繼承自Animal,具有Animal的屬性和方法,當然其繼承的屬性和方法還在Animal的命名空間;
AnimalType = 'Dog' # 此處的賦值不會影響父類中的AnimalType。給誰賦值就會在誰的命名空間創建一個新對象(當對象不存在時)
def __init__(self,name = 'Dog',age = 3):
Animal.__init__(self,name) # 調用父類的初始化函數,name存在於實例的命名空間中
# super().__init__(name) # 也可以通過使用 super() 來調用父類的方法
self.age = age # 給子類的實例添加新的屬性
def eat(self):
print('in Dog-喫喫!')
class Tiger(Animal):
AnimalType = 'Tiger'
def __init__(self, name='Tiger'):
# Animal.__init__(self, name) #
super().__init__( name) #
def eat(self):
print('in Tiger-喫!')
print('1:類中的屬性與方法:'+'*'*60)
print(Animal.__dict__)
print(Dog.__dict__)
print(Tiger.__dict__)
animal = Animal('小動物')
dog = Dog('小狗狗')
tiger = Tiger('小老虎')
print('2:實例中的屬性與方法:'+'*'*60)
print(animal.__dict__)
print(dog.__dict__)
print(tiger.__dict__)
print('3:實例的方法調用:'+'*'*60)
animal.eat()
animal.showInfo()
print('*'*25)
dog.eat()
dog.showInfo()
print('*'*25)
tiger.eat()
tiger.showInfo()
print('*'*25)
print('4:多態:'+'*'*60)
"""
餵養動物:
不需要知道是何種類型的動物,只要是繼承自Animal的即可,
不夠是現在已有的子類還是將來新增加的子類,下面的類都是
可用的。
"""
class Breeder:
def feed(self,animal): #
animal.eat()
animal.showInfo()
bd = Breeder()
lst = []
lst.append(dog)
lst.append(animal)
lst.append(tiger)
for an in lst:
bd.feed(an)
3:多繼承
python中支持多繼承,即子類可以繼承多個父類的屬性和方法。python中使用多繼承,會涉及到查找順序(MRO)、重複調用(鑽石繼承,也叫菱形繼承問題)等
MRO即method resolution order,用於判斷子類調用的屬性來自於哪個父類。在Python3中使用C3算法,採用廣度優先搜索。
在Pythop中,對屬性的引用以及方法的調用都會按照MRO的順序來確定其屬於哪個類中;對屬性的賦值都會在其對應的類或實例中創建屬性,與MRO無關。
示例代碼:
# encoding=gbk
class Base:
def func(self):
print('in Base - func ')
def func2(self):
print('in Base - func2 ')
class A(Base):
def func(self):
print('in A - func ')
class B(Base):
def func(self):
print('in B - func ')
def func2(self):
print('in B - func2 ')
class C(A,B,Base):
def func(self):
print('in C - func ')
class D(C):
pass
print(D.mro())
d = D()
d.func()
d.func2() # 按照MRO的順序找func2,會在類B中找到
"""
輸出:
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
in C - func
in B - func2
"""
4:內置函數super()
4.1:初始化中使用super()
在Python中super()表示其父類,在初始化中會按照MRO的順序分別調用父類的初始化函數,示例如下:
# encoding=gbk
class Base:
def __init__(self,val):
print('init--Base')
self.val = val
def func(self):
print('in Base - func ')
def func2(self):
print('in Base - func2 ')
class A(Base):
def __init__(self,val):
print('init--A')
super().__init__(val)
# super(A,self).__init__(val)
self.val += 2
def func(self):
print('in A - func ')
class B(Base):
def __init__(self,val):
print('init--B')
super().__init__(val)
# super(B,self).__init__(val)
self.val += 3
def func(self):
print('in B - func ')
def func2(self):
print('in B - func2 ')
class C(A,B,Base):
def __init__(self,val):
print('init--C')
super().__init__(val)
# super(C,self).__init__(val)
self.val += 4
def func(self):
print('in C - func ')
class D(C):
pass
print(D.mro())
d = D(0)
print('1:'+'*'*30)
d.func()
print('2:'+'*'*30)
d.func2()
"""
輸出:
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
init--C
init--A
init--B
init--Base
1:******************************
in C - func
2:******************************
in B - func2
"""
4.2:方法調用中使用super()
按照MRO的順序調用第一個找到的方法:
# encoding=gbk
class Base:
def func(self):
print('in Base - func ')
def func2(self):
print('in Base - func2 ')
class A(Base):
def func(self):
print('in A - func ')
class B(Base):
def func(self):
print('in B - func ')
def func2(self):
print('in B - func2 ')
class C(A,B,Base):
def func(self):
print('in C - func ')
class D(C):
def func(self):
super().func()
def func2(self):
super().func2()
print(D.mro())
d = D()
d.func()
d.func2()
"""
輸出結果:
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
in C - func
in B - func2
"""
4.3:運行時修改其父類
# encoding=gbk
class X:
def func(self):
print('X.func')
class Y:
def func(self):
print('Y.func')
class Z(X):
def func(self):
# X.func(self) # 這樣寫,下面的改變基類操作將會不起作用,
super().func()
z = Z()
print(Z.__bases__ )
z.func()
Z.__bases__ = (Y,) # 修改其父類爲Y
print(Z.__bases__ )
z.func()
"""
輸出:
(<class '__main__.X'>,)
X.func
(<class '__main__.Y'>,)
Y.func
"""
5:Python3中的抽象基類
抽象基類:即不能實例化的類。
在Python3中帶有抽象方法的類就是抽象基類,其子類必須實現抽象方法。
# encoding=gbk
from abc import ABCMeta,abstractmethod
class Base(metaclass=ABCMeta):
def delegate(self):
self.func()
@abstractmethod
def func(self):
pass
# b = Base() #TypeError: Can't instantiate abstract class Base with abstract methods func
class Sub(Base):
def func(self):
print('in Sub --func')
s = Sub()
s.delegate() # 首先調用父類中的方法delegate(),delegate()方法這依據self(即子類的實例)調用func
"""
輸出:in Sub --func
"""