1. 你知道什么是Python里的鴨子類型和猴子補(bǔ)丁嗎?

        共 2163字,需瀏覽 5分鐘

         ·

        2021-10-14 15:49

        有時候我們會聽到Python里所謂的鴨子類型猴子補(bǔ)丁的說法,乍一聽還以為是來到了動物園,Python這只大蟒蛇還可以和鴨子和猴子一起玩耍?


        非也非也,鴨子類型和猴子補(bǔ)丁實際上是兩個生動有趣的比喻,用來說明Python的動態(tài)特性。


        鴨子類型??(duck type) 是對Python中數(shù)據(jù)類型本質(zhì)上是由屬性和行為來定義的一種解讀。


        猴子補(bǔ)丁??(monkey patching)是對Python中類和模塊可以在外部被動態(tài)修改這種特性的一個比喻。


        讓我們來一探究竟吧!


        一,鴨子類型

        鴨子類型是對Python中數(shù)據(jù)類型本質(zhì)上是由屬性和行為來定義的一種解讀。


        Python是一種動態(tài)語言,不像Java和C++這種強(qiáng)類型語言,Python里實際上沒有嚴(yán)格的類型檢查。


        只要某個對象具有鴨子的方法,可以像鴨子那樣走路和嘎嘎叫,那么它就可以被其它函數(shù)當(dāng)做鴨子一樣調(diào)用。


        #?這是一個鴨子(Duck)類
        class?Duck:
        ????def?__init__(self,name):
        ????????self.name?=?name
        ????def?swim(self):
        ????????print("A?duck?named?"?+?self.name+"?is?swimming...")
        ????def?call(self):
        ????????print("gay...gay...gay...")

        #?這是一個鵝(Goose)類
        class?Goose:
        ????def?__init__(self,name):
        ????????self.name?=?name
        ????def?swim(self):
        ????????print("A?goose?named?"?+?self.name+"?is?swimming...")
        ????def?call(self):
        ????????print("goo...goo...goo...")

        # duckshow這個函數(shù)設(shè)計的本意是需要傳入一個Duck對象作為參數(shù)的。?
        def?duckshow(duck):
        ????duck.swim()
        ????duck.call()

        yaya?=?Duck("yaya")
        ee?=?Goose("ee")

        #?但由于Python是動態(tài)語言,其數(shù)據(jù)類型屬于鴨子類型,沒有嚴(yán)格類型檢查,
        #?Goose這個類具有和Duck這個類相同的方法,
        #?ee這只鵝劃起水來像只鴨子,叫起來也像一只鴨子,
        #?所以duckshow這個函數(shù)也可以對ee進(jìn)行作用。

        duckshow(yaya)
        duckshow(ee)

        輸出結(jié)果如下:
        A duck named yaya is swimming...gay ... gay ... gay ...A goose named ee is swimming...goo ... goo ... goo ...

        二,猴子補(bǔ)丁

        猴子補(bǔ)丁是對Python中模塊和類可以在外部被動態(tài)修改這種特性的一個比喻。


        為什么叫做猴子補(bǔ)丁呢?在模塊和類的外部對模塊和類進(jìn)行修改是一種非常耍賴的做法,會破壞代碼的封裝結(jié)構(gòu),這種事情大概只有淘氣的猴子喜歡去做,因此形象地稱之為猴子補(bǔ)丁。


        #?定義一個Dog類
        class?Dog:
        ????def?__init__(self,name,age):
        ????????self.name?=?name
        ????????self.age?=?age

        ????def?sleep(self):
        ????????print("Zzz...Zzz..Zzz...")

        #?在類的外部給Dog這個類添加猴子補(bǔ)丁
        def?speak(self):
        ????print("I?think?myself?a?hero?and?very?handsome!")

        Dog.speak?=?speak
        Dog.home?=?"Earth"

        #?與類的內(nèi)部定義的屬性和方法無差異
        snoopy?=?Dog("snoopy",3)
        snoopy.sleep()
        snoopy.speak()
        print(snoopy.home)


        輸出結(jié)果如下:

        Zzz?...?Zzz?...?Zzz?...I think myself a hero and very handsome!Earth


        對于庫中已經(jīng)定義好的類,給它們添加猴子補(bǔ)丁有時候會非常方便,相當(dāng)于可以自由地在外面做擴(kuò)展,又不用修改源文件。


        import?numpy?as?np
        import?pandas?as?pd

        df?=?pd.DataFrame(np.random.randint(1,10,size=(5,5)),
        ??????????????????columns?=?list("abcde"))
        #df.info()
        #DataFrame自帶方法info打印信息太多,展示不直觀。
        #給DataFrame定義一個猴子補(bǔ)丁方法memory簡潔展示其內(nèi)存消耗。

        def?memory(self):
        ????mem?=?self.__sizeof__()
        ????if?mem<1024:
        ????????return("%s?B"%mem)
        ????elif?mem<1024*1024:
        ????????return("%s?KB"%mem/1024)
        ????elif?mem<1024**3:
        ????????return("%s?MB"%mem/1024**2)
        ????else:
        ????????return("%s?GB"%mem/1024**3)?

        pd.DataFrame.memory?=?memory

        print(df.memory())


        輸出結(jié)果如下:

        280 B


        這就是Python里的鴨子類型和猴子補(bǔ)丁的一個簡單介紹,你耍明白了嗎?????????????


        瀏覽 39
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報
          
          

            1. 黄色成人视频在线免费看 | 97超碰超碰 | 男女啪祼交视频 | 91精品国产91综合久久蜜臀 | 浪逼天天操 |