1. 淺談Python鴨子類型

        共 4392字,需瀏覽 9分鐘

         ·

        2021-05-02 08:51

        目錄

        • 1、什么是“鴨子類型”

        • 2、“鴨子類型”從何而來

          • 2.1 多態(tài)

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

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

        • 3、小結(jié)


        1、什么是“鴨子類型”

        Python崇尚“鴨子類型”

        對于鴨子類型常見的說法是:“當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子?!?/p>

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

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

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

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

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

        2、“鴨子類型”從何而來

        2.1 多態(tài)

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

        大學時學習過C、Java基礎(chǔ)這一類強類型語言,面向?qū)ο缶幊痰娜筇匦灾挥袀€概念叫做“多態(tài)”

        簡單來說,定義時的類型和運行時的類型不一樣就是多態(tài)

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

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

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

        例如下面代碼示例:

        • 程序在運行到list這一步是只把Cat,DogDuck當成變量

        • 只有在最后實例化調(diào)用類方法的時候才會明白是一個類,這就表示多態(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)的使用

        再來一個偏實際的應(yīng)用示例代碼

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

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

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

        class AliPay(Payment):

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

        class WeChatPay(Payment):

            def pay(self):
                # 微信提供了一個網(wǎng)絡(luò)上的聯(lián)系渠道
                print('%s通過微信消費了%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)

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

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

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

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

        order.account(Payment pay_obj)),所以你傳入別的類型對象一定報錯

        但是python因為是動態(tài)語言所以傳入的對象只要擁有調(diào)用的方法即可視為Payment類型對象,這就是所謂的鴨子類型

        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類擁有跟Duck類一樣的方法,當有一個函數(shù)調(diào)用Duck類,并利用到了兩個方法walk()swim()。我們傳入Person類也一樣可以運行,函數(shù)并不會檢查對象的類型是不是Duck,只要他擁有walk()swim()方法,就可以正確的被調(diào)用

        3、小結(jié)

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

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

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

        如果這些需要被調(diào)用的方法不存在,那么將引發(fā)一個運行時錯誤

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

        • 鵝不是鴨子,但是鵝一旦擁有鴨子的一些方法,就可以被當成鴨子類型了

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

        • 鴨子類型使用的前提是需要良好的文檔支持,不然會讓代碼變得很混亂,如果沒有良好的文檔及說明,有可能會導致你的“鴨子”不是我的“鵝”了

        瀏覽 54
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 国产靠逼片直接看的 | 欧美日韩成人一区二区三区 | 精品无码人妻一区 | 国产视频激情 | 午夜理伦三级做爰电影 |