Python-裝飾器上下五千年和前世今生

來源:互聯網
上載者:User

標籤:最新   調用   class   傳回值   解決   添加   直接   highlight   tar   

  裝飾器上下五千年和前世今生,這裡我們始終要問,裝飾器為何產生?裝飾器產生解決了什麼問題?什麼樣的需求推動了裝飾器的產生?思考問題的時候,始終要問,為什麼要這樣,而不是那樣或者其他樣。這裡我不先說,也不直接把裝飾器的最終樣子擺出來,而是說說裝飾器發展過程,從這些過程中知道,不是技術推動技術的發展,而是解決這個需求推動技術的產生。接下來一步步構建裝飾器產生的過程,從最原始的方向來到最新的狀態來解說裝飾器為何產生,裝飾器產生的過程是如何演變的。

下面是一段簡代碼,實現的功能是暫停1秒,然後再列印一句問好"Hai, 北門吹雪"

import timedef bei_men_chui_xue():    time.sleep(1)    print("Hai, 北門吹雪")bei_men_chui_xue()

這裡需求來了,誰誰誰,總是在提需求,殺了祭天。

哎呀,在這個功能上在添加一個小小的功能,就是一個小小功能,輸出一下這個功能的已耗用時間,不難吧?

默默的掏出身後的板磚,啪的一下拍在桌子上,昨天晚上你不是這樣說的,說好不改需求的,今天早上就翻臉了?

好吧,我默默的去改需求了,提交了方案 1

import timedef bei_men_chui_xue():    time.sleep(1)    print("Hai, 北門吹雪")start_time = time.time()bei_men_chui_xue()print("run time:", time.time() - start_time)

雖然實現了這個需求,但是這個直接內嵌程式碼邏輯,把功能代碼邏輯包圍了起來,看起來不夠優雅,改得好看點好嗎?

好吧,我又默默器去修改需求了,提交了方案2

import timedef bei_men_chui_xue():    time.sleep(1)    print("Hai, 北門吹雪")def get_run_time(func):    start_time = time.time()    func()    end_time = time.time()    print(end_time - start_time)# 高階函數,已經很優雅的解決方案get_run_time(bei_men_chui_xue)

很好,使用了高階函數,居然知道Python中一切皆對象的原理,把擷取時間的功能封裝成一個函數,試試用閉包去實現?

好吧,我又默默器去修改需求了,提交了方案3

import timedef bei_men_chui_xue():    time.sleep(1)    print("Hai, 北門吹雪")def get_run_time(func):    def wrapper():        start_time = time.time()        func()        end_time = time.time()        print(end_time - start_time)    return wrapper# 閉包解決方案,看起來方案2遠比這個優雅f = get_run_time(bei_men_chui_xue)f()

嗯,非常好,我也覺得方案2好,但是你修改了源碼,改變了源碼的執行邏輯,嘗試不改變源碼邏輯?

好吧,我又默默器去修改需求了,提交了方案4

import timedef get_run_time(func):    def wrapper():        start_time = time.time()        func()        end_time = time.time()        print(end_time - start_time)    return wrapper@get_run_timedef bei_men_chui_xue():    time.sleep(1)    print("Hai, 北門吹雪")# 裝飾器解決方案,前面的文法糖才是裝飾器核心bei_men_chui_xue()

不錯不錯,裝飾器把被裝飾函數傳遞進裝飾器,調用源函數其實本質上調用裝飾器中的wrapper函數,我想在原函數傳遞進去參數,如何?

好吧,我又默默器去修改需求了,提交了方案5

import timedef get_run_time(func):    def wrapper(*args, **kwargs):        start_time = time.time()        func(*args, **kwargs)        end_time = time.time()        print(end_time - start_time)    return wrapper@get_run_timedef bei_men_chui_xue(name):    time.sleep(1)    print("Hai, %s" % name)# 解決裝飾的函數有變數bei_men_chui_xue("北門吹雪")

很好,很好,通過往裝飾器中傳遞 *args **kwargs參數完成向原函數傳遞參數,我想獲得一下原函數的傳回值?如被裝飾函數的傳回值?

好吧,我又默默器去修改需求了,提交了方案6

import timedef get_run_time(func):    def wrapper(*args, **kwargs):        start_time = time.time()        r = func(*args, **kwargs)        end_time = time.time()        run_time = end_time - start_time        print(run_time)        # 被裝飾函數傳回值        return r    return wrapper@get_run_timedef bei_men_chui_xue(name):    time.sleep(1)    return "Hai, %s" % name# 解決裝飾的函數有變數r = bei_men_chui_xue("北門吹雪")print(r)

功能還需要改動,我不想輸出其已耗用時間,可以通過向裝飾器中傳入參數,如果已耗用時間超過這個數列印已經逾時?

好吧,我又默默器去修改需求了,提交了方案7

import timedef get_run_time(time_out):    def out_wrapper(func):        def wrapper(*args, **kwargs):            start_time = time.time()            r = func(*args, **kwargs)            end_time = time.time()            # 擷取已耗用時間            run_time = end_time - start_time            # 檢查程式已耗用時間是否逾時            if run_time > time_out:                print("已耗用時間已經逾時")            # 被裝飾函數傳回值            return r        return wrapper    return out_wrapper@get_run_time(time_out=1)def bei_men_chui_xue(name):    time.sleep(1)    return "Hai, %s" % namebei_men_chui_xue("北門吹雪")# 擷取傳回值r = bei_men_chui_xue("北門吹雪")print(r)

完美,這個才是五彩斑斕的黑,加個雞腿

從這個過程中可以看出,被裝飾函數運行時候其實啟動並執行是裝飾器內部wrapper函數,通過函數閉包實現對一些參數狀態的儲存,從而實現各種需求的裝飾器

Python-裝飾器上下五千年和前世今生

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.