<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
        當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

        分析Python中設(shè)計(jì)模式之Decorator裝飾器模式的要點(diǎn)

        來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 14:35:34
        文檔

        分析Python中設(shè)計(jì)模式之Decorator裝飾器模式的要點(diǎn)

        分析Python中設(shè)計(jì)模式之Decorator裝飾器模式的要點(diǎn):先給出一個(gè)四人團(tuán)對(duì)Decorator mode的定義:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。 再來(lái)說(shuō)說(shuō)這個(gè)模式的好處:認(rèn)證,權(quán)限檢查,記日志,檢查參數(shù),加鎖,等等等等,這些功能和系統(tǒng)業(yè)務(wù)無(wú)關(guān),但又是系統(tǒng)所必須的,說(shuō)的更明白一點(diǎn),就是面向方面的編程(AOP)
        推薦度:
        導(dǎo)讀分析Python中設(shè)計(jì)模式之Decorator裝飾器模式的要點(diǎn):先給出一個(gè)四人團(tuán)對(duì)Decorator mode的定義:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。 再來(lái)說(shuō)說(shuō)這個(gè)模式的好處:認(rèn)證,權(quán)限檢查,記日志,檢查參數(shù),加鎖,等等等等,這些功能和系統(tǒng)業(yè)務(wù)無(wú)關(guān),但又是系統(tǒng)所必須的,說(shuō)的更明白一點(diǎn),就是面向方面的編程(AOP)

        先給出一個(gè)四人團(tuán)對(duì)Decorator mode的定義:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。
        再來(lái)說(shuō)說(shuō)這個(gè)模式的好處:認(rèn)證,權(quán)限檢查,記日志,檢查參數(shù),加鎖,等等等等,這些功能和系統(tǒng)業(yè)務(wù)無(wú)關(guān),但又是系統(tǒng)所必須的,說(shuō)的更明白一點(diǎn),就是面向方面的編程(AOP)。
        在Python中Decorator mode可以按照像其它編程語(yǔ)言如C++, Java等的樣子來(lái)實(shí)現(xiàn),但是Python在應(yīng)用裝飾概念方面的能力上遠(yuǎn)不止于此,Python提供了一個(gè)語(yǔ)法和一個(gè)編程特性來(lái)加強(qiáng)這方面的功能。Python提供的語(yǔ)法就是裝飾器語(yǔ)法(decorator),如下:

        @aoo
        def foo(): pass
        def aoo(fn):
         return fn
        

        裝飾模式強(qiáng)調(diào)動(dòng)態(tài)地給對(duì)象添加額外的功能。 Python內(nèi)置了很多對(duì)裝飾器的支持,因此在Python中使用裝飾模式是非常容易的,下面是一個(gè)典型的例子,給函數(shù)增加日志功能:

        import functools
        def log_wrapper(fun):
         @functools.wraps(fun)
         def wrapper(*args, **kwargs):
         print '在函數(shù)執(zhí)行前加日志'
         ret = fun(*args, **kwargs)
         print '在函數(shù)執(zhí)行后家日志'
         return ret
         return wrapper
        
        
        @log_wrapper
        def test():
         print 'Hello, 世界'
        
        

        functools.wraps是Python標(biāo)準(zhǔn)庫(kù)提供的一個(gè)特殊的裝飾器,用來(lái)解決裝飾器帶來(lái)的一些常規(guī)問(wèn)題,如函數(shù)名稱、doc等的不一致問(wèn)題。@是Python針對(duì)裝飾器提供的一個(gè)語(yǔ)法糖,上面的@log_wrapper相當(dāng)于wrap_test = log_rapper(test),用@后,這個(gè)步驟由解釋器代勞了。

        裝飾器是Python編程必須掌握的一項(xiàng)技能,在編碼過(guò)程中經(jīng)常會(huì)用到。

        這里只是一個(gè)普通的內(nèi)嵌函數(shù)

        def foo(x):
         y = x
         def foo1 ():
         a = 1
         return a
         return foo1
        

        而下面boo則是一個(gè)閉包

        def aoo(a, b):
         c = a
         def boo (x):
         x = b + 1
         return x
         return boo
        

        boo的特殊性在于引用了外部變量b,當(dāng)aoo返回后,只要返回值(boo)一直存在,則對(duì)b的引用就會(huì)一直存在。
        上面的知識(shí)可能需要花些時(shí)間消化,如果你覺(jué)得已經(jīng)掌握了這些知識(shí),下面就回歸正題,看看這些語(yǔ)言特性是怎樣來(lái)實(shí)現(xiàn)Python中裝飾的概念的。
        還是讓我們先看一個(gè)簡(jiǎn)單的例子,然后逐步深入。這個(gè)例子就是加鎖,怎樣實(shí)現(xiàn)加鎖的功能?
        具體需求是這樣的:我有一個(gè)對(duì)象,實(shí)現(xiàn)了某些功能并提供了一些接口供其它模塊調(diào)用,這個(gè)對(duì)象是運(yùn)行在并發(fā)的環(huán)境中的,因此我需要對(duì)接口的調(diào)用進(jìn)行同步,第一版的代碼如下:

        class Foo(object):
         def __init__(self, …):
         self.lock = threading.Lock()
         def interface1(self, …):
         self.lock.acquire()
         try:
         do something
         finally:
         self.lock.release()
         def interface2(self, …):
         same as interface1()
         …
        

        這版代碼的問(wèn)題很明顯,那就是每個(gè)接口函數(shù)都有相同的加鎖/解鎖代碼,重復(fù)的代碼帶來(lái)的是更多的鍵入,更多的閱讀,更多的維護(hù),以及更多的修改,最主要的是,程序員本應(yīng)集中在業(yè)務(wù)上的的精力被分散了,而且請(qǐng)注意,真正的業(yè)務(wù)代碼在距離函數(shù)定義2次縮進(jìn)處開(kāi)始,即使你的顯示器是寬屏,這也會(huì)帶來(lái)一些閱讀上的困難。
        你直覺(jué)的認(rèn)為,可以把這些代碼收進(jìn)一個(gè)函數(shù)中,以達(dá)到復(fù)用的目的,但是請(qǐng)注意,這些代碼不是一個(gè)完整同一的代碼塊,而是在中間嵌入了業(yè)務(wù)代碼。
        現(xiàn)在我們用裝飾器語(yǔ)法來(lái)改進(jìn)這部分代碼,得到第2版代碼:

        def sync(func):
         def wrapper(*args, **kv):
         self = args[0]
         self.lock.acquire()
         try:
         return func(*args, **kv)
         finally:
         self.lock.release()
         return wrapper
        class Foo(object):
         def __init__(self, …):
         self.lock = threading.Lock()
         @sync
         def interface1(self, …):
         do something
         @sync
         def interface2(self, …):
         do something
         …
        

        一個(gè)裝飾器函數(shù)的第一個(gè)參數(shù)是所要裝飾的那個(gè)函數(shù)對(duì)象,而且裝飾器函數(shù)必須返回一個(gè)函數(shù)對(duì)象。如sync函數(shù),當(dāng)其裝飾interface1時(shí),參數(shù)func的值就是interface1,返回值是wrapper,但類Foo實(shí)例的interface1被調(diào)用時(shí),實(shí)際調(diào)用的是wrapper函數(shù),在wrapper函數(shù)體中間接調(diào)用實(shí)際的interface1;當(dāng)interface2被調(diào)用時(shí),也調(diào)用的是wrapper函數(shù),不過(guò)由于在裝飾時(shí)func已經(jīng)變成interface2,所以會(huì)間接地調(diào)用到實(shí)際的interface2函數(shù)。
        使用裝飾器語(yǔ)法的好處:
        代碼量大大的減少了,更少的代碼意味著更少的維護(hù),更少的閱讀,更少的鍵入,好處不一而足(可復(fù)用,可維護(hù))
        用戶基本上將絕大部分精力放在了業(yè)務(wù)代碼上,而且少了加減鎖的代碼,可讀性也提高了
        缺點(diǎn):
        業(yè)務(wù)對(duì)象Foo中有一個(gè)非業(yè)務(wù)數(shù)據(jù)成員lock,很礙眼;
        相當(dāng)程度的耦合,wrapper的第一個(gè)參數(shù)必須是對(duì)象本身,而且被裝飾的對(duì)象中必須有一個(gè)lock對(duì)象存在,這給客戶對(duì)象添加了限制,使用起來(lái)不是很舒服。
        我們可以更進(jìn)一步想一想:
        lock對(duì)象必須要放在Foo中嗎?
        為每個(gè)接口函數(shù)都鍵入@sync還是很煩人的重復(fù)性人工工作,如果漏添加一個(gè),還是會(huì)造成莫名其妙的運(yùn)行時(shí)錯(cuò)誤,為什么不集中處理呢?
        為了解決上述的缺點(diǎn),第3版代碼如下:

        class DecorateClass(object):
         def decorate(self):
         for name, fn in self.iter():
         if not self.filter(name, fn):
         continue
         self.operate(name, fn)
        class LockerDecorator(DecorateClass):
         def __init__(self, obj, lock = threading.RLock()):
         self.obj = obj
         self.lock = lock
         def iter(self):
         return [(name, getattr(self.obj, name)) for name in dir(self.obj)]
         def filter(self, name, fn):
         if not name.startswith('_') and callable(fn):
         return True
         else:
         return False
         def operate(self, name, fn):
         def locker(*args, **kv):
         self.lock.acquire()
         try:
         return fn(*args, **kv)
         finally:
         self.lock.release()
         setattr(self.obj, name, locker)
        class Foo(object):
         def __init__(self, …):
         …
         LockerDecorator(self).decorate()
         def interface1(self, …):
         do something
         def interface2(self, …):
         do something
         …
        

        對(duì)對(duì)象的功能裝飾是一個(gè)更一般的功能,不僅限于為接口加鎖,我用2個(gè)類來(lái)完成這一功能,DecorateClass是一個(gè)基類,只定義了遍歷并應(yīng)用裝飾功能的算法代碼(template method),LockerDecorator實(shí)現(xiàn)了為對(duì)象加鎖的功能,其中iter是迭代器,定義了怎樣遍歷對(duì)象中的成員(包括數(shù)據(jù)成員和成員函數(shù)),filter是過(guò)濾器,定義了符合什么規(guī)則的成員才能成為一個(gè)接口,operate是執(zhí)行函數(shù),具體實(shí)施了為對(duì)象接口加鎖的功能。
        而在業(yè)務(wù)類Foo的__init__函數(shù)中,只需要在最后添加一行代碼:LockerDecorator(self).decorate(),就可以完成為對(duì)象加鎖的功能。
        如果你的對(duì)象提供的接口有特殊性,完全可以通過(guò)直接改寫filter或者繼承LockerDecorator并覆蓋filter的方式來(lái)實(shí)現(xiàn);此外,如果要使用其他的裝飾功能,可以寫一個(gè)繼承自DecorateClass的類,并實(shí)現(xiàn)iter,filter和operate三個(gè)函數(shù)即可。

        聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        分析Python中設(shè)計(jì)模式之Decorator裝飾器模式的要點(diǎn)

        分析Python中設(shè)計(jì)模式之Decorator裝飾器模式的要點(diǎn):先給出一個(gè)四人團(tuán)對(duì)Decorator mode的定義:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。 再來(lái)說(shuō)說(shuō)這個(gè)模式的好處:認(rèn)證,權(quán)限檢查,記日志,檢查參數(shù),加鎖,等等等等,這些功能和系統(tǒng)業(yè)務(wù)無(wú)關(guān),但又是系統(tǒng)所必須的,說(shuō)的更明白一點(diǎn),就是面向方面的編程(AOP)
        推薦度:
        • 熱門焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲美女大bbbbbbbbb| 亚洲成在人天堂在线| 无码的免费不卡毛片视频| 成人人免费夜夜视频观看| 国产香蕉九九久久精品免费 | 日韩人妻无码精品久久免费一| 亚洲女人被黑人巨大进入| 香港特级三A毛片免费观看| www国产亚洲精品久久久日本| 色网站在线免费观看| 亚洲综合区小说区激情区 | 久久精品国产96精品亚洲| 亚洲人成网国产最新在线| 久久久久久久久久免免费精品| 久久精品国产亚洲AV不卡| 免费黄网站在线观看| 久久亚洲精品无码aⅴ大香| 成人免费视频网址| 深夜a级毛片免费视频| 亚洲人成人网站色www| 5555在线播放免费播放| 亚洲色大成WWW亚洲女子| 亚洲精品高清在线| 野花香高清在线观看视频播放免费| 亚洲国产香蕉碰碰人人| 国产成人精品免费视频大全| 亚洲乱码一区二区三区在线观看| 亚洲国产午夜精品理论片在线播放 | 亚洲AⅤ男人的天堂在线观看| 国产又粗又猛又爽又黄的免费视频| 人人爽人人爽人人片av免费| 国产av无码专区亚洲av桃花庵| 无码精品人妻一区二区三区免费| 亚洲日产韩国一二三四区| 毛片免费全部播放无码| 免费亚洲视频在线观看| 国产18禁黄网站免费观看| 精品一卡2卡三卡4卡免费视频| 亚洲中文字幕一二三四区苍井空| 免费无码A片一区二三区| 国产免费A∨在线播放|