13-面向?qū)ο?

13-面向?qū)ο?

  • 1、繼承簡(jiǎn)介
    • 繼承是面向?qū)ο笕筇匦灾?/li>
    • 通過(guò)繼承我們可以使一個(gè)類獲取到其他類中的屬性和方法
    • 在定義類時(shí),可以在類名后面的括號(hào)中指定當(dāng)前類的父類(超類、基類)
    • 繼承提高了類的復(fù)用性。讓類與類之間產(chǎn)生了關(guān)系。有了這個(gè)關(guān)系,才有了多態(tài)的特性
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/9/17 0017 21:02
# @Author  : Oliver
#繼承是面向?qū)ο蟮娜筇匦灾?# 通過(guò)繼承我們可以使一個(gè)類獲取其他類的屬性和方法
# class Person():
#     name=''
#     age=''
# class Doctor():
#     name=''
#     age=''
#
#     def heal(self):
#         print('治病救人!')
#
# class Student():
#     name=''
#     age=''
#
#     def study(self):
#         print('好好學(xué)習(xí),天天向上?。?!')
#
# object是所有類的父類
# issubclass()檢查一個(gè)類是不是另一個(gè)類的子類
class Animal(object):
    def run(self):
        print('動(dòng)物跑起來(lái)了.....')
    def sleep(self):
        print('動(dòng)物睡覺(jué)...')

a=Animal()
# a.run()

# 需求:定義一個(gè)狗類
# 1.直接修改Animal這個(gè)類,在這個(gè)類中添加我們需要的功能
# 這種方式比較麻煩,并且會(huì)違反OCP原則
# 顯然這個(gè)方式不推薦
# 2.直接創(chuàng)建一個(gè)新的類
# 創(chuàng)建一個(gè)新類是比較麻煩的,并且需要大量的賦值粘貼,會(huì)出現(xiàn)大量的重復(fù)代碼
# class Dog():
#     def run(self):
#         print('狗跑起來(lái)了.....')
#     def sleep(self):
#         print('狗睡覺(jué)...')
#     def speak(self):
#         print('汪汪汪!')
#
# 3.直接從Animal類中繼承他的屬性和方法
# 在定義類的時(shí)候,可以在類名的后面加上一個(gè)括號(hào),這個(gè)括號(hào)中可以指定當(dāng)前類的父類(超類、基類)
class Dog(Animal):
    def speak(self):
        print('汪汪汪!')
    def run(self):
        print('狗再跑?。?)#更新了狗的方法
d=Dog()
# Dog中沒(méi)有sleep的方法,但是父類有,很明顯d可以調(diào)用,這就是Dog繼承了Animal這個(gè)父類的方法和屬性
d.run()
d.sleep()
d.speak()
#判斷d是不是Dog的實(shí)例
r=isinstance(d,Dog)
print(r)#最后發(fā)現(xiàn)是的
#判斷d是不是Animal的實(shí)例
r=isinstance(d,Animal)
print(r)#最后發(fā)現(xiàn)是的
# 也就是d也是父類的實(shí)例
print()

print(issubclass(Dog,Animal))
print(issubclass(Animal,object))

結(jié)果顯示:

狗再跑!!
動(dòng)物睡覺(jué)...
汪汪汪!
True
True

True
True

Process finished with exit code 0

  • 2、方法重寫
    • 如果在子類中有和父類同名的方法,則通過(guò)子類實(shí)例去調(diào)用方法時(shí),會(huì)調(diào)用子類的方法而不是父類的方法,這個(gè)特點(diǎn)我們稱之為方法的重寫(覆蓋)
    • 當(dāng)我們調(diào)用一個(gè)對(duì)象的方法時(shí):
      • 會(huì)優(yōu)先去當(dāng)前對(duì)象中尋找是否具有該方法,如果有則直接調(diào)用
      • 如果沒(méi)有,則去當(dāng)前對(duì)象的父類中尋找,如果父類中有則直接調(diào)用父類中的方法
      • 如果沒(méi)有,則去父類中的父類尋找,以此類推,直到找到object,如果依然沒(méi)有找到就報(bào)錯(cuò)了
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/9/17 0017 21:27
# @Author  : Oliver
# 重寫/覆蓋(override)

class A(object):
    def test(self):
        print('A....')
class B(A):
    def test(self):
        print('B....')
class C(B):
    pass
c=C()
c.test()

結(jié)果顯示:

B....

Process finished with exit code 0
  • 3、super()
    • super()可以獲取當(dāng)前類的父類
    • 并且通過(guò)super()返回對(duì)象調(diào)用父類方法時(shí),不需要傳遞self
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/9/17 0017 21:37
# @Author  : Oliver
# 父類中所有的方法都會(huì)被子類繼承,包括特殊的方法
class Animal(object):
    def __init__(self,name,sex):
        self._name=name
        self._sex=sex

    @property
    def sex(self):
        return self._sex

    @sex.setter
    def sex(self, sex):
        self._sex = sex
    @property
    def name(self):
        return self._name

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

    def run(self):
        print('動(dòng)物跑起來(lái)了.....')
    def sleep(self):
        print('動(dòng)物睡覺(jué)...')

class Dog(Animal):
    def __init__(self,name,age,sex):
        # self._name=name
        # self._age=age
        # self._sex=sex
        # Animal.__init__(self,name,sex)
        super().__init__(name,sex)
    @property
    def age(self):
        return self._age

    @age.setter
    def age(self,age):
        self._age = age
    def speak(self):
        print('汪汪汪?。?!')
    def run(self):
        print('狗在跑.....')

d=Dog('試試',4,'男')
print(d.name)
print(d.sex)

# super()可以獲取當(dāng)前類的父類

  • 4、多重繼承
    • 在Python中是支持多重繼承的。也就是我們可以為一個(gè)類同時(shí)制定多個(gè)父類
    • 可以在類名的()后邊添加多個(gè)類,來(lái)實(shí)現(xiàn)多重繼承
    • 多重繼承,會(huì)使子類同時(shí)擁有多個(gè)父類,并且會(huì)獲取到所有父類中的方法
    • 在開(kāi)發(fā)中沒(méi)有特殊情況,應(yīng)該盡量避免使用多重繼承。因?yàn)槎嘀乩^承會(huì)讓我們的代碼更加復(fù)雜
    • 如果多個(gè)父類中有同名的方法,則會(huì)先在第一個(gè)父類中尋找,如果該父類還有父類,則在該父類的父類中查找,沒(méi)有的話,然后找第二個(gè),找第三個(gè)...前面會(huì)覆蓋后面的
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/9/18 0018 12:34
# @Author  : Oliver
# 類名.__bases__這個(gè)屬性可以用來(lái)獲取當(dāng)前類的父類
class A(object):
    def test(self):
        print('A....')
class B(object):
    def test(self):
        print('B....')
# 可以在類名的()后邊添加多個(gè)類,來(lái)實(shí)現(xiàn)多重繼承
class C(A,B):
    pass
c=C()
print(C.__bases__)
# (<class '__main__.B'>,)元組還有逗號(hào),說(shuō)明可以有多個(gè)父類
print(B.__bases__)
c.test()
# 多個(gè)父類中有同名的方法,則會(huì)先在第一個(gè)父類中尋找,然后找第二個(gè),找第三個(gè)...前面會(huì)覆蓋后面的

結(jié)果顯示:

(<class '__main__.A'>, <class '__main__.B'>)
(<class 'object'>,)
A....

Process finished with exit code 0

  • 5、多態(tài)
    • 多態(tài)是面向?qū)ο蟮娜筇匦灾?。從字面理解就是多種形態(tài)
    • 一個(gè)對(duì)象可以以不同形態(tài)去呈現(xiàn)
    • 面向?qū)ο笕筇匦?
      • 封裝 確保對(duì)象中數(shù)據(jù)的安全
      • 基礎(chǔ) 保證了對(duì)象的擴(kuò)展性
      • 多態(tài) 保證了程序的靈活性
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/9/18 0018 12:50
# @Author  : Oliver

# 多態(tài)也是面向?qū)ο蟮娜筇匦灾?# 一個(gè)對(duì)象可以以不同的形態(tài)去呈現(xiàn)
class A:
    def __init__(self,name):
        self._name=name

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

class B:
    def __init__(self, name):
        self._name = name

    @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()
# 定義一個(gè)函數(shù)  這種形式就是多態(tài)
def speak(obj):
    print('你好%s'%obj.name)
# 只要對(duì)象有name就可以,不用對(duì)象是A,還是B
# 適應(yīng)性更高

speak(a)
# speak(c)
# 這種形式就違反了一個(gè)多態(tài)的原則
def speak2(obj):
    # 類型檢查
    if isinstance(obj,A):#只能處理一類對(duì)象
        print('你好%s'%obj.name)

speak2(a)


# 舉個(gè)例子好理解
lst=[1,2,3]
print(len(lst))
s='python'
print(len(s))
# len()可以處理不同對(duì)象,就相當(dāng)于上述的speak()
# 這就是一個(gè)多態(tài)
# 列表字符串都封裝了__len__,這是他們的共同點(diǎn)

  • 6、屬性和方法
    • 屬性
      • 類屬性,直接在類中定義的屬性是類屬性
      • 類屬性可以通過(guò)類或類的實(shí)例訪問(wèn)到。但是類屬性只能通過(guò)類對(duì)象來(lái)修改,無(wú)法通過(guò)實(shí)例對(duì)象修改
      • 實(shí)例屬性 通過(guò)實(shí)例對(duì)象添加的屬性屬于實(shí)例屬性
      • 實(shí)例屬性只能通過(guò)實(shí)例對(duì)象來(lái)訪問(wèn)和修改,類對(duì)象無(wú)法訪問(wèn)修改
    • 方法
      • 在類中定義,以self為第一個(gè)參數(shù)的方法都是實(shí)例方法
      • 實(shí)例方法在調(diào)用時(shí),Python會(huì)將調(diào)用對(duì)象以self傳入
      • 實(shí)例方法可以通過(guò)類實(shí)例和類去調(diào)用
      • 當(dāng)通過(guò)實(shí)例調(diào)用時(shí),會(huì)自動(dòng)將當(dāng)前調(diào)用對(duì)象作為self傳入
      • 當(dāng)通過(guò)類調(diào)用時(shí),不會(huì)自動(dòng)傳遞self,我們必須手動(dòng)傳遞self
      • 類方法 在類的內(nèi)容以@classmethod 來(lái)修飾的方法屬性類方法
      • 類方法第一個(gè)參數(shù)是cls 也會(huì)自動(dòng)被傳遞。cls就是當(dāng)前的類對(duì)象
      • 類方法和實(shí)例方法的區(qū)別,實(shí)例方法的第一個(gè)參數(shù)是self,類方法的第一個(gè)參數(shù)是cls
      • 類方法可以通過(guò)類去調(diào)用,也可以通過(guò)實(shí)例調(diào)用
    • 靜態(tài)方法
      • 在類中用@staticmethod來(lái)修飾的方法屬于靜態(tài)方法
      • 靜態(tài)方法不需要指定任何的默認(rèn)參數(shù),靜態(tài)方法可以通過(guò)類和實(shí)例調(diào)用
      • 靜態(tài)方法,基本上是一個(gè)和當(dāng)前類無(wú)關(guān)的方法,它只是一個(gè)保存到當(dāng)前類中的函數(shù)
      • 靜態(tài)方法一般都是些工具方法,和當(dāng)前類無(wú)關(guān)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/9/18 0018 13:24
# @Author  : Oliver

class A:
    # 類屬性:直接在類中定義的屬性就是類屬性
    # 類屬性可以通過(guò)類對(duì)象和實(shí)例對(duì)象來(lái)訪問(wèn)
    # 類屬性只能通過(guò)類對(duì)象來(lái)修改,不能通過(guò)實(shí)例對(duì)象來(lái)修改
    count=0
    def __init__(self):
        self.name='張三'
        #  這其實(shí)是一個(gè)實(shí)例屬性,因?yàn)閟elf就是a,通過(guò)self將這個(gè)屬性添加到了當(dāng)前的實(shí)例對(duì)象中

        # 這是實(shí)例方法
    def test(self):
        print('這是個(gè)test方法!?。?)
    # 類方法
    #在類的內(nèi)部使用@classmethod修飾的方式屬于類方法
    # 類方法的第一個(gè)參數(shù)cls,也會(huì)自動(dòng)傳遞,cls表示的就是當(dāng)前的類對(duì)象
    @classmethod
    def test2(cls):
        print('這是個(gè)test2方法?。?!')
        print(cls.count)
    # 靜態(tài)方法
    # 在類中被@staticmethod來(lái)修飾的方法屬于靜態(tài)方法
    @staticmethod
    def test3(self):
        print('這是個(gè)test3方法?。?!')
a=A()
# 實(shí)例屬性:通過(guò)實(shí)例對(duì)象添加的屬性是實(shí)例屬性
# a.count=10
# A.count=10
# print('A',A.count)
# print('a',a.count)
#
# print('a',a.name)
# print('A',A.name)這個(gè)是會(huì)報(bào)錯(cuò)的
# 實(shí)例屬性只能通過(guò)實(shí)例對(duì)象來(lái)訪問(wèn)、修改,類對(duì)象無(wú)法訪問(wèn)修改

a.test()
A.test(a)
# a.test()等價(jià)于A.test(a)
A.test2()
a.test2()
# A.test2()等價(jià)于a.test2()

A.test3()
a.test3()

結(jié)果顯示:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/9/18 0018 13:24
# @Author  : Oliver

class A:
    # 類屬性:直接在類中定義的屬性就是類屬性
    # 類屬性可以通過(guò)類對(duì)象和實(shí)例對(duì)象來(lái)訪問(wèn)
    # 類屬性只能通過(guò)類對(duì)象來(lái)修改,不能通過(guò)實(shí)例對(duì)象來(lái)修改
    count=0
    def __init__(self):
        self.name='張三'
        #  這其實(shí)是一個(gè)實(shí)例屬性,因?yàn)閟elf就是a,通過(guò)self將這個(gè)屬性添加到了當(dāng)前的實(shí)例對(duì)象中

        # 這是實(shí)例方法
    def test(self):
        print('這是個(gè)test方法?。?!')
    # 類方法
    #在類的內(nèi)部使用@classmethod修飾的方式屬于類方法
    # 類方法的第一個(gè)參數(shù)cls,也會(huì)自動(dòng)傳遞,cls表示的就是當(dāng)前的類對(duì)象
    @classmethod
    def test2(cls):
        print('這是個(gè)test2方法!?。?)
        print(cls.count)
    # 靜態(tài)方法
    # 在類中被@staticmethod來(lái)修飾的方法屬于靜態(tài)方法
    @staticmethod
    def test3(self):
        print('這是個(gè)test3方法?。。?)
a=A()
# 實(shí)例屬性:通過(guò)實(shí)例對(duì)象添加的屬性是實(shí)例屬性
# a.count=10
# A.count=10
# print('A',A.count)
# print('a',a.count)
#
# print('a',a.name)
# print('A',A.name)這個(gè)是會(huì)報(bào)錯(cuò)的
# 實(shí)例屬性只能通過(guò)實(shí)例對(duì)象來(lái)訪問(wèn)、修改,類對(duì)象無(wú)法訪問(wèn)修改

a.test()
A.test(a)
# a.test()等價(jià)于A.test(a)
A.test2()
a.test2()
# A.test2()等價(jià)于a.test2()

A.test3()
a.test3()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容