第十六章: 面向對象 - 繼承和多態

01 - 面向對象 - 繼承簡介

1.提高了代碼的複用性 2.讓類與類之間產生關係,有了這個關係,纔有了多態的特性

class Person():

    name = ''
    age = ''

class Doctor():

    name = ''
    age = ''

    def zhibing(self):

        print('治療病人')

class soldier():
    name = ''
    age = ''

    def baowei(self):
        print('保衛國家')

1.繼承的簡介
1.提高了代碼的複用性 2.讓類與類之間產生關係,有了這個關係,纔有了多態的特性
3.繼承也是面向對象的三大特徵之一

定義一個動物類

如何能讓這個當前的動物類實現全部的功能
1.直接修改這個動物類,在這個類中添加我們需要的功能
2.可以直接創建一個新類
3.直接從動物類中繼承它的屬性和方法
在創建類的時候,如果我們省略父類則默認父類爲object
所有類都繼承object,object是所有類的父類

class Animal:

    def run(self):
        print('動物在跑')

    def sleep(self):
        print('動物在睡覺')

    # def speak(self):
    #     print('動物會叫')

class cat():

    def run(self):
        print('貓在跑')

    def sleep(self):
        print('貓在睡覺')

    def speak(self):
        print('貓在叫')

class cat(Animal):

    def run(self):

        print('貓在跑')

    def speak(self):

        print('喵喵喵')


# a = Animal()
c = cat()
# print(c)
c.run()
# c.sleep()
# c.speak()

# r = isinstance(c,Animal)
# issubclass()

class Person():
    pass

print(issubclass(cat,Animal))
print(issubclass(Animal,object))
print(issubclass(Person,object))
# print(issubclass(print,object))   # 不能這麼寫
print(isinstance(print,object))

>>>
貓在跑
True
True
True
True

2. - 面向對象 - 重寫


class Animal:

    def run(self):
        print('動物在跑')

    def sleep(self):
        print('動物在睡覺')

    # def speak(self):
    #     print('動物會叫')

class cat():

    def run(self):
        print('貓在跑')

    def sleep(self):
        print('貓在睡覺')

    def speak(self):
        print('貓在叫')

# 如果子類中有父類同名的方法,則通過子類的實例去調用該方法時, 會調用子類的方法而不是父類的方法,這個特點也稱之爲我們所說的方法重寫(覆蓋)
class cat(Animal):

    # def run(self):
    #
    #     print('貓在跑')

    def speak(self):

        print('喵喵喵')


# a = Animal()
c = cat()
# print(c)
# c.run()
# c.sleep()
# c.speak()


# 當我們調用一個對象的方法時
# 會優先去當前對象中去尋找是否有該方法,如果有則直接調用
# 如果沒有,則去當前對象的父類中尋找,如果父類中有則直接調用
# 如果沒有,則去父類對象中的父類中去尋找,以此類推,直到找到object,如果沒有則報錯
class A(object):

    def text(self):

        print('AAA')

class B(A):

    def text(self):

        print('BBB')

class C(B):
    def text(self):

        print('CCC')

c = C()

c.text()


>>>

CCC

03.面向對象 - supper()

class Animal:

    def __init__(self,name):

        self._name = name

    def run(self):
        print('動物在跑')

    def sleep(self):
        print('動物在睡覺')

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self,name):
        self._name = name
# 三、supper()
# 父類中的所有方法都會被子類繼承,包括特殊方法
class cat(Animal):

    # 我希望可以直接調用父類中的__init__方法來初始化父類中的屬性
    # supper()可以獲得當前類的父類
    # 通過supper()返回對象調應父類方法時,不需要傳遞self
    def __init__(self,name,age):
        Animal.__init__(self,name)  # 或者 supper().__init__(name)
        # self._name = name
        self._age = age

    def run(self):
        print('貓在跑')

    def speak(self):
        print('喵喵喵')

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age


c = cat('波斯貓',44)
c.name = '加菲貓'

print(c.name)
print(c.age)

>>>
加菲貓
44

04 - 面向對象 - 多重繼承

Python中支持多重繼承,也就是我們可以爲一個類同時制定多個父類
bases
語法 類名 .__bases__可以獲取當前類所有的父類

class A(object):

    def text(self):

        print('AAA')

class B(object):

    def text(self):

        print('BBB')

class C(B):

    pass

print(C.__bases__)   # 打印結果是一個元組 打印結果:(<class '__main__.B'>,)
print(B.__bases__)   # 打印結果是一個元組 打印結果:(<class 'object'>,)


class A(object):

    def text(self):

        print('AAA')

class B(object):

    def text(self):

        print('BBB')

class C(A,B):

    pass

print(C.__bases__)  #打印結果是兩個元組 打印結果:(<class '__main__.A'>, <class '__main__.B'>)


# 我們在開發的時候儘量不要用多重繼承,原因是增加我們代碼的複雜程度
# 如果多個父類中出現重名的方法,則會先在第一個父類中尋找,然後再找第二個,再找第三個,後邊會覆蓋前邊

class A(object):

    def text(self):

        print('AAA')

class B(object):

    def text2(self):

        print('BBB')

class C(A,B):

    pass

c = C()
c.text()   # AAA
c.text2()  # BBB

# 05. - 多態


多態也是面向對象的三大特性之一
一個對象可以以不同的邢臺去呈現

鴨子類型:
如果有一個東西 走路像鴨子 ,叫聲像鴨子,那麼它就是鴨子

```python
class A:

    def __init__(self,name):

        self._nmae = name


    @property
    def name(self):
        return self._name

    @name.setter
    def name(self,name):
        self._name = name


class B:

    def __init__(self, name):
        self._nmae = name

    def __len__(self):
        return 10

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name

class C:
    pass

a = A('葫蘆娃')
b = B('鋼鐵俠')
c = C()

def say(obj):

    print('你好 %s'%obj.name)


def say2(obj):

    # 做類型檢查
    # 違反了多態的函數只適用於一種類型的對象,無法處理其他誒行的對象,這樣會導致函數的適用性非常差
    if isinstance(obj,A):

        print('你好 %s'%obj.name)

# say(c)
# say2(b)  # Process finished with exit code 0

# len()
# 之所以一個對象能夠通過len()函數獲取長度,是因爲對象中具有一個特殊方法__len__
lst = [1,2,3]
s = 'Python'
# print(len(lst))

# print(len(s))

print(len(b))   # 10
print(len(c))   # TypeError: object of type 'C' has no len()
                # c這個對象沒有len()這個函數

# 面相對象的三大 特徵 :    封裝:確保對象中數據的安全  繼承;保證了對象的可擴展  多態:保證了程序的靈活性

06. - 面向對象 - 屬性和方法

# 類方法和實例方法的區別:實例方法第一個參數是self,類方法第一個參數是cls
class A(object):

    # 類屬性  直接在類中第一個屬性就是類屬性
    # 類屬性可以通過類本身或者是類的實例訪問
    # 類屬性  只能通過類對象來修改,無法通過實例對象來修改
    count = 0

    # 實例屬性,通過實例對象添加的屬性叫做實例屬性
    # 實例屬性  只能通過實例對象來訪問和修改,類對象無法訪問和修改

    def __init__(self):

        self.name = '葫蘆娃'

    # 實例方法
    # 在類中定義,以self爲參數的方法都是實例方法
    # 實例方法在調用時,Python會將調用的對象作爲self傳入
    #當通過類調用時,不會自動傳入self
    def text(self):

        print('這是text方法',self)

    # 類方法
    # 在類的內部使用 @classmethod 來修飾的方法叫做類方法
    # 類方法第一個參數是cls  會被自動上傳 cls就是當前的類對象
    @classmethod
    def text2(cls):
        print('這是text2方法',cls)
        print(cls.count)

    # 靜態方法
    # 在類中內部使用@staticmethod 來修飾的方法屬於靜態方法
    # 靜態方法不需要指定任何默認的參數,靜態方法可以通過類和實例去調用
    @staticmethod
    def text3():

        print('text3執行了')


a = A()

# a.count = 5
# A.count = 5
# print('A',A.name) # AttributeError: type object 'A' has no attribute 'name'
print('a',a.name)   #  a 葫蘆娃

a.text()    # 這是text方法 <__main__.A object at 0x000001E4EA0C0BE0>
A.text(a)   # 這是text方法 <__main__.A object at 0x000001E4EA0C0BE0>  # a.text() 等價於 A.text(a)

A.text2()  # 這是text2方法 <class '__main__.A'>
            # 0
a.text2()  # 這是text2方法 <class '__main__.A'> # A.text2() 等價於 a.text2()
            # 0

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