Python3面向對象-繼承與多態

目錄

1:繼承與多態介紹

2:繼承與多態示例代碼

3:多繼承

4:內置函數super()

4.1:初始化中使用super()

4.2:方法調用中使用super()

4.3:運行時修改其父類

5:Python3中的抽象基類


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
"""

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章