<p id="m2nkj"><option id="m2nkj"><big id="m2nkj"></big></option></p>
    <strong id="m2nkj"></strong>
    <ruby id="m2nkj"></ruby>

    <var id="m2nkj"></var>
  • 淺談Python鴨子類(lèi)型

    共 4392字,需瀏覽 9分鐘

     ·

    2021-05-02 08:51

    目錄

    • 1、什么是“鴨子類(lèi)型”

    • 2、“鴨子類(lèi)型”從何而來(lái)

      • 2.1 多態(tài)

      • 2.2 多態(tài)的使用

      • 2.3 鴨子類(lèi)型產(chǎn)生

    • 3、小結(jié)


    1、什么是“鴨子類(lèi)型”

    Python崇尚“鴨子類(lèi)型”

    對(duì)于鴨子類(lèi)型常見(jiàn)的說(shuō)法是:“當(dāng)看到一只鳥(niǎo)走起來(lái)像鴨子、游泳起來(lái)像鴨子、叫起來(lái)也像鴨子,那么這只鳥(niǎo)就可以被稱為鴨子。”

    鴨子類(lèi)型(英語(yǔ):duck typing)在程序設(shè)計(jì)中是動(dòng)態(tài)類(lèi)型的一種風(fēng)格。在這種風(fēng)格中,一個(gè)對(duì)象有效的語(yǔ)義,不是由繼承自特定的類(lèi)或?qū)崿F(xiàn)特定的接口,而是由“當(dāng)前方法和屬性的集合”決定

    在鴨子類(lèi)型中,關(guān)注點(diǎn)在于對(duì)象的行為能做什么;而不是關(guān)注對(duì)象所屬的類(lèi)型。例如,在不使用鴨子類(lèi)型的語(yǔ)言中,我們可以編寫(xiě)一個(gè)函數(shù),它接受一個(gè)類(lèi)型為"鴨子"的對(duì)象,并調(diào)用它的"走"和"叫"方法。在使用鴨子類(lèi)型的語(yǔ)言中,這樣的一個(gè)函數(shù)可以接受一個(gè)任意類(lèi)型的對(duì)象,并調(diào)用它的"走"和"叫"方法。如果這些需要被調(diào)用的方法不存在,那么將引發(fā)一個(gè)運(yùn)行時(shí)錯(cuò)誤。任何擁有這樣的正確的"走"和"叫"方法的對(duì)象都可被函數(shù)接受的這種行為引出了以上表述,這種決定類(lèi)型的方式因此得名

    鴨子類(lèi)型通常得益于"不"測(cè)試方法和函數(shù)中參數(shù)的類(lèi)型,而是依賴文檔、清晰的代碼和測(cè)試來(lái)確保正確使用

    在常規(guī)類(lèi)型中,我們能否在一個(gè)特定場(chǎng)景中使用某個(gè)對(duì)象取決于這個(gè)對(duì)象的類(lèi)型,而在鴨子類(lèi)型中,則取決于這個(gè)對(duì)象是否具有某種屬性或者方法——即只要具備特定的屬性或方法,能通過(guò)鴨子測(cè)試,就可以使用。

    內(nèi)容參考自維基百科:https://zh.wikipedia.org/wiki/%E9%B8%AD%E5%AD%90%E7%B1%BB%E5%9E%8B

    2、“鴨子類(lèi)型”從何而來(lái)

    2.1 多態(tài)

    先來(lái)看看“多態(tài)”

    大學(xué)時(shí)學(xué)習(xí)過(guò)CJava基礎(chǔ)這一類(lèi)強(qiáng)類(lèi)型語(yǔ)言,面向?qū)ο缶幊痰娜筇匦灾挥袀€(gè)概念叫做“多態(tài)”

    簡(jiǎn)單來(lái)說(shuō),定義時(shí)的類(lèi)型和運(yùn)行時(shí)的類(lèi)型不一樣就是多態(tài)

    更通俗的來(lái)說(shuō),多態(tài)是指一類(lèi)事物有多種形態(tài)。比如動(dòng)物有多種形態(tài),人、狗、貓等等

    放到二進(jìn)制的世界,例如文件,文件有多種形態(tài):文本文件、可執(zhí)行文件

    總而言之,多態(tài)即某類(lèi)的再分類(lèi),再分的每一類(lèi)就是父類(lèi)的多種形態(tài)的一種

    例如下面代碼示例:

    • 程序在運(yùn)行到list這一步是只把CatDogDuck當(dāng)成變量

    • 只有在最后實(shí)例化調(diào)用類(lèi)方法的時(shí)候才會(huì)明白是一個(gè)類(lèi),這就表示多態(tài)

    class Cat(object):
        def info(self):
            print("我是一只貓")


    class Dog(object):
        def info(self):
            print("我是一只狗")


    class Duck(object):
        def info(self):
            print("我是一只鴨")

    list=[Cat,Dog,Duck]
    for animal in list:
        animal().info()

    2.2 多態(tài)的使用

    再來(lái)一個(gè)偏實(shí)際的應(yīng)用示例代碼

    from abc import ABCMeta,abstractmethod #(抽象方法)

    class Payment(metaclass=ABCMeta):   # metaclass 元類(lèi)  metaclass = ABCMeta表示Payment類(lèi)是一個(gè)規(guī)范類(lèi)
        def __init__(self,name,money):
            self.money=money
            self.name=name

        @abstractmethod      # @abstractmethod表示下面一行中的pay方法是一個(gè)必須在子類(lèi)中實(shí)現(xiàn)的方法
        def pay(self,*args,**kwargs):
            pass

    class AliPay(Payment):

        def pay(self):
            # 支付寶提供了一個(gè)網(wǎng)絡(luò)上的聯(lián)系渠道
            print('%s通過(guò)支付寶消費(fèi)了%s元'%(self.name,self.money))

    class WeChatPay(Payment):

        def pay(self):
            # 微信提供了一個(gè)網(wǎng)絡(luò)上的聯(lián)系渠道
            print('%s通過(guò)微信消費(fèi)了%s元'%(self.name,self.money))


    class Order(object):

        def account(self,pay_obj):
            pay_obj.pay()

    pay_obj = WeChatPay("wang",100)
    pay_obj2 = AliPay("zhang",200)

    order = Order()
    order.account(pay_obj)
    order.account(pay_obj2)

    從上述代碼可見(jiàn),在調(diào)用order對(duì)象的account()方法時(shí),程序并不關(guān)心為該方法傳入的參數(shù)對(duì)象pay_obj是誰(shuí),只要求此參數(shù)對(duì)象pay_obj包含pay()方法即可,而調(diào)用者傳入的參數(shù)對(duì)象類(lèi)型pay_obj是子類(lèi)對(duì)象還是其他類(lèi)對(duì)象,對(duì)Python來(lái)說(shuō)無(wú)所謂

    多態(tài)性就是相同的消息(函數(shù)方法觸發(fā))使得不同的類(lèi)做出不同的響應(yīng),這就是典型的類(lèi)編程中多態(tài)性的應(yīng)用實(shí)例

    2.3 鴨子類(lèi)型產(chǎn)生

    在上面的例子中order.account(pay_obj)pay_obj不需要類(lèi)型聲明,而java在使用時(shí)要定義好類(lèi)型

    order.account(Payment pay_obj)),所以你傳入別的類(lèi)型對(duì)象一定報(bào)錯(cuò)

    但是python因?yàn)槭莿?dòng)態(tài)語(yǔ)言所以傳入的對(duì)象只要擁有調(diào)用的方法即可視為Payment類(lèi)型對(duì)象,這就是所謂的鴨子類(lèi)型

    class Duck():
        def walk(self):
            print('I walk like a duck')
        def swim(self):
            print('i swim like a duck')

    class Person():
        def walk(self):
          print('this one walk like a duck'
        def swim(self):
          print('this man swim like a duck')

    可以很明顯的看出,Person類(lèi)擁有跟Duck類(lèi)一樣的方法,當(dāng)有一個(gè)函數(shù)調(diào)用Duck類(lèi),并利用到了兩個(gè)方法walk()swim()。我們傳入Person類(lèi)也一樣可以運(yùn)行,函數(shù)并不會(huì)檢查對(duì)象的類(lèi)型是不是Duck,只要他擁有walk()swim()方法,就可以正確的被調(diào)用

    3、小結(jié)

    • 在鴨子類(lèi)型中,關(guān)注的不是對(duì)象的類(lèi)型本身,而是它是如何使用的

    例如,在不使用鴨子類(lèi)型的語(yǔ)言中,我們可以編寫(xiě)一個(gè)函數(shù),它接受一個(gè)類(lèi)型為"鴨子"的對(duì)象,并調(diào)用它的"走"和"叫"方法

    • 在使用鴨子類(lèi)型的語(yǔ)言中,這樣的一個(gè)函數(shù)可以接受一個(gè)任意類(lèi)型的對(duì)象,并調(diào)用它的"走"和"叫"方法

    如果這些需要被調(diào)用的方法不存在,那么將引發(fā)一個(gè)運(yùn)行時(shí)錯(cuò)誤

    任何擁有這樣的正確的"走"和"叫"方法的對(duì)象都可被函數(shù)接受的這種行為引出了以上表述,這種決定類(lèi)型的方式因此得名

    • 鵝不是鴨子,但是鵝一旦擁有鴨子的一些方法,就可以被當(dāng)成鴨子類(lèi)型了

    • 鴨子類(lèi)型的好處就在于能夠避免一些類(lèi)的重寫(xiě),無(wú)需大量復(fù)制相同的代碼

    • 鴨子類(lèi)型使用的前提是需要良好的文檔支持,不然會(huì)讓代碼變得很混亂,如果沒(méi)有良好的文檔及說(shuō)明,有可能會(huì)導(dǎo)致你的“鴨子”不是我的“鵝”了

    瀏覽 54
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評(píng)論
    圖片
    表情
    推薦
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    <p id="m2nkj"><option id="m2nkj"><big id="m2nkj"></big></option></p>
    <strong id="m2nkj"></strong>
    <ruby id="m2nkj"></ruby>

    <var id="m2nkj"></var>
  • 亚洲一区二区三区 | 久爱福利在线 | 国产综合久久777777歌曲 | www国产夜插内射视频网站 | 韩国免费一区二区三区 | 可以免费观看的黄色视频 | 2018天天日天天干 | 国产免费黄色电影在线观看 | 国产三级在线免费 | 丁香五月婷婷亚洲 |