日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

Python中的Mixin详解

發(fā)布時(shí)間:2023/12/31 python 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python中的Mixin详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一些閑聊:

Mixin是一種設(shè)計(jì)模式、設(shè)計(jì)思想

并不是某個(gè)特定的class或者函數(shù).

Java中的Mixin叫interface

Ruby中的Mixin叫Module

[2]優(yōu)點(diǎn):

1.mixin設(shè)計(jì)迷失可以在不對類的內(nèi)容的修改前提下,擴(kuò)展類的功能(添加父類)
2.更加方便的組織和維護(hù)不同的組建
3.可以根據(jù)開發(fā)需要任意調(diào)整功能
4.可以避免產(chǎn)生更多的類

缺點(diǎn):
受繼承關(guān)系限制,推薦只有兩層的繼承使用。

#-------------------------------------------------

案例一[3]:

class Role:def walk(self):print('走')#--------------------------------------------------------------- class RunMixin:def run(self):print('跑')class PromptSkillMixin:def use_prompt_skill(self):print('使用了一個(gè)瞬發(fā)技能')class WalkExMixin:#覆蓋Role中的功能,因?yàn)橄旅媸亲钕壤^承,Role是最后繼承def walk(self):print('疾走')class RoleEx(WalkExMixin, PromptSkillMixin, RunMixin, Role):def marco(self):return [self.run, self.use_prompt_skill]def use_marco(self):print("---------------use_marco技術(shù)----------------")for action in self.marco():action()print("--------use_marco結(jié)束----------") if __name__ == '__main__':r = RoleEx()r.use_marco()r.walk()

實(shí)驗(yàn)結(jié)果:

---------------use_marco技術(shù)----------------

使用了一個(gè)瞬發(fā)技能
--------use_marco結(jié)束------------------
疾走

?

這個(gè)案例顯而易見的好處是:

你在不用修改Role的情況下擴(kuò)展了很多功能.

因?yàn)橛械臅r(shí)候,Role這個(gè)是由你的同事開發(fā)的,你沒有修改的權(quán)限,你的同事僅僅給了你調(diào)用接口的權(quán)限,

或者說,為了免責(zé)和穩(wěn)定,比如到時(shí)候出問題誰背鍋啊,你不被公司允許修改原來的代碼.

#------------------------------------------------

案例二[1]:

class Displayer():def display(self, message):print("--------②這里是Displayer.display函數(shù)---start-----")print("Displayer的self=",self)print(message)print("--------②這里是Displayer.display函數(shù)---end-----\n")class LoggerMixin():def log(self, message, filename='logfile.txt'):print("MySubClass self=",self)with open(filename, 'a') as fh:print("--------③這里是LoggerMixin.log函數(shù)---start-----")fh.write(message)print("--------③這里是LoggerMixin.log函數(shù)---end-----\n")def display(self, message):print("display的self=",self)#這里的self類指代的是MySubClass,并不是LoggerMixinprint("------①這里是LoggerMixin的display函數(shù)-start--\n")super().display(message)#會(huì)調(diào)用Displayer.display()函數(shù)self.log(message)print("------①這里是LoggerMixin的display函數(shù)-end--\n")class MySubClass(LoggerMixin, Displayer):def log(self, message):super().log(message, filename='subclasslog.txt')subclass = MySubClass() subclass.display("This string will be shown and logged in subclasslog.txt")''' 1. MySubClass.display() is resolved to LoggerMixin.display(). MySubClass.display() 方法被解析為 LoggerMixin.display() 方法的調(diào)用。 這應(yīng)該還是比較好理解的。因?yàn)閷τ?MySubClass 類來說, 在繼承鏈上的兩個(gè)父類,LoggerMixin 和 Displayer 來說,LoggerMixin 是最近的,因此調(diào)用它的 display() 方法。2. LoggerMixin.display() calls super().display(), which is resolved to Displayer.display(). LoggerMixin.display() 方法調(diào)用了 super().display(),這一行代碼按照我們剛才的解釋,查看 MySubClass 的繼承鏈, 是應(yīng)該調(diào)用 Displayer 類的 display() 方法的。這一步是相對來說比較難以理解的。讓我們這么來理解它,當(dāng) LoggerMixin.display() 中調(diào)用了 super().display() 的時(shí)候,它會(huì)嘗試去尋找屬于當(dāng)前類的繼承鏈。而這個(gè)當(dāng)前類是什么類呢? 不是 LoggerMixin 類,而是 MySubClass 類。MySubClass 類的繼承連是 LoggerMixin,然后 Displayer。所以,我們就找到了 Displayer 的 display() 方法。3. It alse calls self.log(). Since self, in this case, is a MySubClass instance, it resolves to MySubClass.log(). MySubClass.log() calls super().log(), which is resolved back to LoggerMixin.log(). 別忘了,我們的 LoggerMixin 類還調(diào)用了 self.log() 方法。 這個(gè)看似好像要直接調(diào)用 LoggerMixin 的 log 方法,其實(shí)不然。LoggerMixin 的 display() 方法在當(dāng)前語境中的 self,其實(shí)是 MySubClass 類的對象, 因此對于 MySubClass 類的對象,想要調(diào)用 log 方法, 是直接調(diào)用自己類中的 log 方法,也就是 MySubClass.log() 方法,而不是 LoggerMixin.log() 方法的。而又因?yàn)?MySubClass.log() 方法調(diào)用了 super().log() 方法,這才根據(jù)繼承鏈尋找最近的父類,才找到了 LoggerMixin 類中的 log() 方法進(jìn)行調(diào)用。

這個(gè)例子在網(wǎng)上非常有名,[1]中分析了這個(gè)例子的細(xì)節(jié),細(xì)節(jié)我已經(jīng)都復(fù)制到上方的代碼中了.

核心思想和目標(biāo)是(個(gè)人分析):

假如沒有LoggerMixin,這個(gè)代碼就剩下Displayer,所以整體代碼的目標(biāo)是:

不修改Displayer的情況下(這個(gè)非常重要),擴(kuò)充Displayer的功能.

#---------------案例二[1]實(shí)驗(yàn)結(jié)果-感性分析-------------------------

實(shí)驗(yàn)結(jié)果如下:

display的self= <__main__.MySubClass object at 0x7f59388331d0>
------①這里是LoggerMixin的display函數(shù)-start--

--------②這里是Displayer.display函數(shù)---start-----
Displayer的self= <__main__.MySubClass object at 0x7f59388331d0>
This string will be shown and logged in subclasslog.txt
--------②這里是Displayer.display函數(shù)---end-----

MySubClass self= <__main__.MySubClass object at 0x7f59388331d0>
--------③這里是LoggerMixin.log函數(shù)---start-----
--------③這里是LoggerMixin.log函數(shù)---end-----

------①這里是LoggerMixin的display函數(shù)-end--

我們很直觀地可以看出:

如果沒有LoggerMixin,那么上述結(jié)果就會(huì)只剩下紅色部分,

當(dāng)前實(shí)驗(yàn)結(jié)果的黑色部分是對原有的Displayer的類的功能進(jìn)行擴(kuò)充.

同時(shí)又確保Displayer的類不被修改

#----------------總結(jié)------------------------

個(gè)人總結(jié)MIXIN的作用:

不修改父類的情況下,對父類的功能進(jìn)行擴(kuò)增和刪改

為什么沒有"査"呢?像數(shù)據(jù)庫那樣的增刪改查.

遺產(chǎn)項(xiàng)目中,同事給你的接口肯定是已經(jīng)實(shí)現(xiàn)"查詢和獲取成員變量"的功能的,即使沒有MIXIN也已經(jīng)具備了"査"功能.

擴(kuò)增:上面兩個(gè)例子都體現(xiàn)了增加功能的作用

刪改:參考上面的案例一,WalkExMixin中的Walk函數(shù)屏蔽了原始父類Role的Walk函數(shù)

所以說,MIXIN這種設(shè)計(jì)模式出現(xiàn)的目的就是:

可以對原始父類實(shí)現(xiàn)功能上的擴(kuò)增和(刪改).

#----------------------------------------

Reference:

[1]一個(gè)例子走近 Python 的 Mixin 類:利用 Python 多繼承的魔力

[2]面向?qū)ο?mixin設(shè)計(jì)模式的應(yīng)用(多繼承應(yīng)用場景)

[3]python_Mixin設(shè)計(jì)模式

總結(jié)

以上是生活随笔為你收集整理的Python中的Mixin详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。