亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

python?中Mixin混入類的使用方法詳解

 更新時(shí)間:2022年07月15日 16:36:03   作者:??DoubleKK?  
這篇文章主要介紹了python?中Mixin混入類的使用方法詳解,Mixin?混入也可以說(shuō)是編程模式,并不是什么新的語(yǔ)法,用好混入類可以使自己的代碼結(jié)構(gòu)清晰,功能明了,所以以后在設(shè)計(jì)類時(shí)要多考慮使用Mixin混入類的實(shí)現(xiàn)方式

前言

最近在看sanic的源碼,發(fā)現(xiàn)有很多Mixin的類,大概長(zhǎng)成這個(gè)樣子

class BaseSanic(
 ? ?RouteMixin,
 ? ?MiddlewareMixin,
 ? ?ListenerMixin,
 ? ?ExceptionMixin,
 ? ?SignalMixin,
 ? ?metaclass=SanicMeta,
):

于是對(duì)于這種 Mixin 研究了一下,其實(shí)也沒(méi)什么新的東西,Mixin 又稱混入,只是一種編程思想的體現(xiàn),但是在使用過(guò)程中還是有一些需要注意的地方。 大家都知道,python 是一種允許多繼承的語(yǔ)言,一個(gè)類可以繼承多個(gè)類,這和java不太一樣,java類只能有一個(gè)父類, 但是java 中有接口的概念,一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,但是java的接口只是定義的函數(shù)的簽名,并沒(méi)有具體的實(shí)現(xiàn),具體的實(shí)現(xiàn)需要相應(yīng)的類來(lái)完成。 python 就不一樣了,一個(gè)類可以有多個(gè)父類,而混入類就是這種允許多繼承語(yǔ)言中才有的一種編程模式。 為了更好的理解混入,我們舉一個(gè)生活中的例子---手機(jī), 手機(jī)有很多功能,由不同的硬件組合而成,手機(jī)有接打電話,收發(fā)短信,上網(wǎng),聽(tīng)歌等功能,組裝一臺(tái)手機(jī)就需要將各種硬件進(jìn)行拼接。 如果我們把這些功能抽象成類,那么我們可以有以下寫法,為了簡(jiǎn)單一點(diǎn),只列接打電話,收發(fā)短信功能。

class Tel:
 ? ?def telfunc(self):
 ? ? ? ?print("我可以接打電話")
 ? ? ? ?class SMS:
 ? ?def smsfunc(self):
 ? ? ? ?print("我可以發(fā)短信")
 ? ? ? ?class Phone:
 ? ?def __init__(self, sn):
 ? ? ? ?self.sn = sn

上面的代碼中, 有三個(gè)類,Tel 類,它有一個(gè) telfunc 方法用于表示有接打電話的能力(或者說(shuō)是功能), SMS 類有smsfunc表示SMS類有發(fā)短信的能力。 而 Phone 這個(gè)類才是一個(gè)手機(jī)類,它應(yīng)該具有接打電話和發(fā)送短信的能力,但是如果我們用上面的方式定義Phone 這個(gè)類,則這個(gè)類并沒(méi)有接打電話和收發(fā)短信的能力。 我們可以怎樣做讓Phone這個(gè)類可以具有打電話和發(fā)短信的能力? 我們可以在Phone 這個(gè)類里再重新定義二個(gè)方法 telfunc和 smsfunc,也就是將Tel類和SMS類里的方法再寫一遍,這種其實(shí)不符合 don't repeate youself的理念。 正常情況下我們是讓Phone這個(gè)類繼承Tel類和SMS類,這樣Phone這個(gè)類就自動(dòng)擁有了接打電話和發(fā)短信的能力了。

class Tel:
 ? ?def telfunc(self):
 ? ? ? ?print("我可以接打電話")
?class SMS:
 ? ?def smsfunc(self):
 ? ? ? ?print("我可以發(fā)短信")
?
?class Phone(Tel, SMS):
 ? ?def __init__(self, sn):
 ? ? ? ?self.sn = sn
? ? ?def welcome(self):
 ? ? ? ?print("welcome {}".format(self.sn))
?p = Phone("xiaomi")
p.telfunc()
p.smsfunc()
p.welcome()
?
'''
我可以接打電話
我可以發(fā)短信
welcome xiaomi
'''

像這種類的定義就是我們所說(shuō)的混入,將通話功能與短信功能加入到手機(jī)中,讓手機(jī)擁有接打電話和發(fā)送短信的功能,這種混入的編碼思想有時(shí)可以減少很多代碼量。很方便的根據(jù)一個(gè)類需要哪些功能就將哪個(gè)類“混入”到該類中。 通常情況下,我們會(huì)將混入類的命名以Mixin結(jié)尾,像上面的代碼我們會(huì)寫成下面這樣

class TelMixin:
 ? ?def telfunc(self):
 ? ? ? ?print("我可以接打電話")
?class SMSMixin:
 ? ?def smsfunc(self):
 ? ? ? ?print("我可以發(fā)短信")
?class Phone(TelMixin, SMSMixin):
 ? ?def __init__(self, sn):
 ? ? ? ?self.sn = sn
? ? ?def welcome(self):
 ? ? ? ?print("welcome {}".format(self.sn))

以 Mixin 結(jié)尾的類,一般是那種功能比較單一,且一般都是某一類型的功能, 如最開始介紹的sanic混入類 RouteMixin 與路由相關(guān)的功能類,MiddlewareMixin 是與中間件相關(guān)的類,ListenerMixin 是監(jiān)聽(tīng)器相關(guān)的類,這些類里的方法專注于自己相關(guān)的功能,如果有哪個(gè)類需要這些功能,那定義的時(shí)候就繼承自這些類。

有人會(huì)問(wèn)了,我不想多繼承,管理MRO 太麻煩了,我只想單繼承,我定義一個(gè)統(tǒng)一的父類,它即有接打電話,也有收發(fā)短信的功能,還可以聽(tīng)歌,然后讓手機(jī)來(lái)繼承這個(gè)類不好嗎?

如下面的代碼:

class Tel:
 ? ?def telfunc(self):
 ? ? ? ?print("我可以接打電話")
 ? ?def smsfunc(self):
 ? ? ? ?print("我可以發(fā)短信")
 ? ?def songfunc(self):
 ? ? ? ?print("我可以放音樂(lè)")
?
?class Phone(Tel):
 ? ?def __init__(self, sn):
 ? ? ? ?self.sn = sn
? ? ?def welcome(self):
 ? ? ? ?print("welcome {}".format(self.sn))

首先這種寫法當(dāng)然是可以的,語(yǔ)法上沒(méi)有任何問(wèn)題,也很好的實(shí)現(xiàn)了相應(yīng)的功能,代碼量也減少了,但是這里大家想一個(gè)邏輯問(wèn)題,如果我想造一個(gè)ipod類,ipod 這個(gè)類沒(méi)有接打電話收發(fā)短信的功能,只有聽(tīng)歌的功能,那么我此時(shí)要寫這個(gè)類該如何定義? 是不是要定義一個(gè)ipod類,然后再寫它的聽(tīng)歌方法songfunc,如果此時(shí)使用混入的編程思想,那么我們就完全可以定義ipod類的時(shí)候 不加入 接打電話和收發(fā)短信的類就可以了。

class TelMixin:
 ? ?def telfunc(self):
 ? ? ? ?print("我可以接打電話")
?class SMSMixin:
 ? ?def smsfunc(self):
 ? ? ? ?print("我可以發(fā)短信")
 ? ? ? ?class SongMixin:
 ? ?def songfunc(self):
 ? ? ? ?print("我可以放音樂(lè)")
?class Phone(TelMixin, SMSMixin, SongMixin):
 ? ?def __init__(self, sn):
 ? ? ? ?self.sn = sn
?class Ipod(SongMixin):
 ? ?def __init__(self, sn):
 ? ? ? ?self.sn = sn

如果還有別的什么類,比如對(duì)講機(jī),它只有接打電話的功能,那么我們就只需要把接打電話的功能混入到對(duì)講機(jī)類即可, class Intercom(TelMixin):

但是有人又會(huì)問(wèn)了,這樣的混入,雖說(shuō)少寫了一些代碼,但是如果子類相應(yīng)實(shí)現(xiàn)并不完全和父類一致該如何處理? 如對(duì)講機(jī)雖然可以通話,但是它是單向通話,并不能雙向通話的。 這時(shí)對(duì)于子類實(shí)現(xiàn)與父類不一致的情況,那么就需要子類重寫父類方法了,也就是OOP中的繼承與多態(tài),嚴(yán)格意義上來(lái)說(shuō), python 并沒(méi)有多態(tài),或者說(shuō)它天然的就是多態(tài)。

class TelMixin:
 ? ?def telfunc(self):
 ? ? ? ?print("我可以接打電話")
?class SMSMixin:
 ? ?def smsfunc(self):
 ? ? ? ?print("我可以發(fā)短信")
?class SongMixin:
 ? ?def songfunc(self):
 ? ? ? ?print("我可以放音樂(lè)")
?class Intercom(TelMixin):
 ? ?def __init__(self, sn):
 ? ? ? ?self.sn = sn
? ? ?def telfunc(self):
 ? ? ? ?print("對(duì)講機(jī){} 的通話".format(self.sn))
?class Phone(TelMixin, SMSMixin, SongMixin):
 ? ?def __init__(self, sn):
 ? ? ? ?self.sn = sn
?class Ipod(SongMixin):
 ? ?def __init__(self, sn):
 ? ? ? ?self.sn = sn
?def testTelfunc(o):
 ? ?o.telfunc()
d = Intercom("moto")
p = Phone("huawei")
ipod = Ipod("apple")
testTelfunc(d)
testTelfunc(p)
testTelfunc(ipod)

以上代碼,我們重寫了對(duì)講機(jī)類的telfunc 方法,但是并沒(méi)有對(duì)Ipod類實(shí)現(xiàn)通話功能, 然后寫了一個(gè)testTelfunc(o) 方法來(lái)調(diào)用傳入?yún)?shù)的通話功能,

得到以下輸出:

#對(duì)講機(jī)moto 的通話
#我可以接打電話
Traceback (most recent call last):
  File "/Users/yyx/test/test.py", line 54, in <module>
    testTelfunc(ipod)
  File "/Users/yyx/test/test.py", line 46, in testTelfunc
    o.telfunc()
AttributeError: 'Ipod' object has no attribute 'telfunc'

當(dāng)給testTelfunc 傳入的是對(duì)講機(jī)Intercom 對(duì)象時(shí),由于該類重寫了telfunc方法,所以這里調(diào)用的是該子類的telfunc方法,當(dāng)傳入的是Phone類對(duì)象時(shí),由于該類繼承了TelMixin類,且沒(méi)有重寫telfunc方法,所以這里會(huì)調(diào)用TelMixin類中的telfunc 方法,但是當(dāng)傳入的是Ipod類時(shí),這個(gè)類既沒(méi)有繼承TelMixin,也沒(méi)有自己的telfunc方法,所以就崩潰了。這也是一種另類的多態(tài)體現(xiàn)吧,只是它沒(méi)有像java中的那么嚴(yán)格。

Mixin 與繼承的區(qū)別

說(shuō)了那么多的Mixin混入,其實(shí)它本質(zhì)上就是繼承,只是這種繼承是存在于允許多繼承的編程語(yǔ)言中,如果說(shuō)區(qū)別,本質(zhì)上也沒(méi)有什么區(qū)別,如果硬是要說(shuō)些區(qū)別,其實(shí)也是有一點(diǎn)點(diǎn)。

  • 首先,Mixin 類最好不要有初始化方法,也就是 __init__ 方法,因?yàn)槿绻鸐ixin類定義了初始化方法,那么在子類中也最好調(diào)用一下父類也就是混入類的初始方法super().__init__(),當(dāng)然不調(diào)用也沒(méi)關(guān)系,IDE 只會(huì)給你一個(gè)提示,語(yǔ)法上并沒(méi)有什么錯(cuò)誤。
  • Mixin 類最好不要單獨(dú)的實(shí)例化,因?yàn)榛烊腩惖脑O(shè)計(jì)初衷就是要讓子類來(lái)繼承的,然后子類可以豐富混入類的功能,混入類只是為了讓子類擁有某些功能而來(lái)的。
  • Mixin 類最好是某一類功能的合集,比如上面sanic 源碼中的 RouteMixin 混入類,它只定義與路由相關(guān)的功能方法,這樣的好處是,不會(huì)有同名的方法,如果混入類中有同名的方法,那么就給自己找麻煩了,排查問(wèn)題也不太好排查,其實(shí)這個(gè)也是比單繼承自一個(gè)類方便的地方。

說(shuō)了那么多Mixin 的好處,它有什么不好的地方嗎? 其實(shí)在我看來(lái),有一個(gè)問(wèn)題,也說(shuō)不上是不好,只是習(xí)慣問(wèn)題,以前寫代碼還是寫單繼承多一些,并不太習(xí)慣這種多繼承的方式,不過(guò)如果一切都按照相應(yīng)的規(guī)則來(lái)操作也不是什么大問(wèn)題。 還有一個(gè)問(wèn)題就是功能的拆分,這個(gè)很是考驗(yàn)編程人員在設(shè)計(jì)代碼之初整體把握能力,就像單體應(yīng)用想要拆分成微服務(wù),邊界問(wèn)題可能是開始時(shí)最頭疼的,拆細(xì)了吧,會(huì)寫出很多類,拆粗了吧,就又回到單繼承的思維模式了,所以這個(gè)也是個(gè)經(jīng)驗(yàn)問(wèn)題吧。

總結(jié)

Mixin 混入也可以說(shuō)是編程模式,并不是什么新的語(yǔ)法,用好混入類可以使自己的代碼結(jié)構(gòu)清晰,功能明了,所以以后在設(shè)計(jì)類時(shí)要多考慮使用Mixin混入類的實(shí)現(xiàn)方式。

到此這篇關(guān)于python 中Mixin混入類的使用方法詳解的文章就介紹到這了,更多相關(guān)python Mixin混入類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 簡(jiǎn)單了解Python matplotlib線的屬性

    簡(jiǎn)單了解Python matplotlib線的屬性

    這篇文章主要介紹了簡(jiǎn)單了解Python matplotlib線的屬性,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-06-06
  • numpy 聲明空數(shù)組詳解

    numpy 聲明空數(shù)組詳解

    今天小編就為大家分享一篇numpy 聲明空數(shù)組詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • Python推導(dǎo)式使用詳情

    Python推導(dǎo)式使用詳情

    這篇文章主要介紹了Python推導(dǎo)式使用詳情,推導(dǎo)式是?for?循環(huán)的簡(jiǎn)化使用方法,使用推導(dǎo)式,將一個(gè)可迭代對(duì)象中的數(shù)據(jù)遍歷到某一個(gè)容器當(dāng)中,下面文章詳細(xì)介紹需要的小伙伴可以參考一下
    2022-05-05
  • Python 通過(guò)xpath屬性爬取豆瓣熱映的電影信息

    Python 通過(guò)xpath屬性爬取豆瓣熱映的電影信息

    我喜歡看電影,可以說(shuō)大部分熱門電影我都看過(guò)。處理愛(ài)好的目的,我看了看豆瓣熱映的電影列表。于是我寫了這個(gè)爬蟲把豆瓣熱映的電影都爬了下來(lái)。對(duì)頁(yè)面的處理主要是需要點(diǎn)擊顯示全部電影,然后爬取影片屬性,最后輸出文本。采用的還是scrapy框架。順便聊聊我的實(shí)現(xiàn)過(guò)程吧
    2021-11-11
  • Python從函數(shù)參數(shù)類型引出元組實(shí)例分析

    Python從函數(shù)參數(shù)類型引出元組實(shí)例分析

    這篇文章主要介紹了Python從函數(shù)參數(shù)類型引出元組,結(jié)合實(shí)例形式分析了Python函數(shù)定義與使用中常見(jiàn)的三種參數(shù)類型,并簡(jiǎn)單分析了元組類型參數(shù)的使用,需要的朋友可以參考下
    2019-05-05
  • python開發(fā)一個(gè)解析protobuf文件的簡(jiǎn)單編譯器

    python開發(fā)一個(gè)解析protobuf文件的簡(jiǎn)單編譯器

    這篇文章主要介紹了python如何開發(fā)一個(gè)解析protobuf文件的簡(jiǎn)單編譯器,幫助大家更好的理解和學(xué)習(xí)python,感興趣的朋友可以了解下
    2020-11-11
  • python 裝飾器的使用與要點(diǎn)

    python 裝飾器的使用與要點(diǎn)

    python的裝飾器本質(zhì)上是一個(gè)Python函數(shù),它可以讓其他函數(shù)在不需要做任何代碼變動(dòng)的前提下增加額外功能;裝飾器的返回值也是一個(gè)函數(shù)對(duì)象。簡(jiǎn)單的說(shuō)裝飾器就是一個(gè)用來(lái)返回函數(shù)的函數(shù)
    2021-05-05
  • python中的split()函數(shù)和os.path.split()函數(shù)使用詳解

    python中的split()函數(shù)和os.path.split()函數(shù)使用詳解

    今天小編就為大家分享一篇python中的split()函數(shù)和os.path.split()函數(shù)使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • python3利用venv配置虛擬環(huán)境及過(guò)程中的小問(wèn)題小結(jié)

    python3利用venv配置虛擬環(huán)境及過(guò)程中的小問(wèn)題小結(jié)

    這篇文章主要介紹了python3利用venv配置虛擬環(huán)境及過(guò)程中的小問(wèn)題小結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • 詳解python和matlab的優(yōu)勢(shì)與區(qū)別

    詳解python和matlab的優(yōu)勢(shì)與區(qū)別

    在本文中小編給大家分享的是關(guān)于python和matlab的優(yōu)勢(shì)與區(qū)別的知識(shí)點(diǎn)以及實(shí)例代碼,需要的朋友們參考學(xué)習(xí)下。
    2019-06-06

最新評(píng)論