Python?中的裝飾器實(shí)現(xiàn)函數(shù)的緩存(場(chǎng)景分析)
裝飾器模式在以下場(chǎng)景中被廣泛應(yīng)用:
- 動(dòng)態(tài)地向?qū)ο筇砑勇氊?zé)或行為,而不需要更改對(duì)象的代碼。例如,可以通過(guò)裝飾器模式來(lái)實(shí)現(xiàn)日志記錄、性能分析、緩存等功能,而不會(huì)影響原始對(duì)象的行為。
- 對(duì)已有對(duì)象進(jìn)行修改時(shí),為避免對(duì)原始對(duì)象的修改,可以使用裝飾器模式。這樣可以將修改限制在裝飾器中,而不會(huì)影響原始對(duì)象。
- 在不同的環(huán)境中使用不同的裝飾器,可以根據(jù)需求動(dòng)態(tài)地添加、刪除、組合和切換不同的裝飾器,從而實(shí)現(xiàn)更大的靈活性和可擴(kuò)展性。例如,在不同的測(cè)試環(huán)境中使用不同的裝飾器,可以方便地對(duì)代碼進(jìn)行測(cè)試和調(diào)試。
- 裝飾器模式可以與其他設(shè)計(jì)模式相結(jié)合,例如工廠模式、單例模式、策略模式等,以實(shí)現(xiàn)更復(fù)雜的功能。例如,可以使用裝飾器模式來(lái)實(shí)現(xiàn)對(duì)工廠模式創(chuàng)建的對(duì)象的動(dòng)態(tài)裝飾
在 Python 中,裝飾器通常是通過(guò)定義一個(gè)新的函數(shù)(即裝飾器函數(shù)),并在該函數(shù)內(nèi)部定義一個(gè) wrapper 函數(shù),通過(guò)調(diào)用 wrapper 函數(shù)來(lái)實(shí)現(xiàn)裝飾器的功能。wrapper 函數(shù)是一個(gè)包裝函數(shù),用于將被裝飾的函數(shù)進(jìn)行包裝和增強(qiáng)。
wrapper 函數(shù)接受任意數(shù)量和類(lèi)型的參數(shù),并且在函數(shù)執(zhí)行前后進(jìn)行一些額外的操作。在函數(shù)執(zhí)行前,wrapper 函數(shù)可以做一些參數(shù)校驗(yàn)、日志記錄、權(quán)限驗(yàn)證等操作,然后將參數(shù)傳遞給被裝飾的函數(shù)。在函數(shù)執(zhí)行后,wrapper 函數(shù)可以根據(jù)函數(shù)的返回值進(jìn)行一些額外的操作,比如緩存計(jì)算結(jié)果、返回特定的錯(cuò)誤信息等。
在裝飾器中,通過(guò)調(diào)用 wrapper 函數(shù)來(lái)代替被裝飾的函數(shù)的執(zhí)行,實(shí)現(xiàn)對(duì)被裝飾函數(shù)的增強(qiáng)和修改。wrapper 函數(shù)的原理是通過(guò)將被裝飾的函數(shù)作為參數(shù)傳遞給 wrapper 函數(shù),在 wrapper 函數(shù)中調(diào)用被裝飾的函數(shù)并返回執(zhí)行結(jié)果,從而實(shí)現(xiàn)對(duì)被裝飾函數(shù)的包裝和增強(qiáng)。同時(shí),wrapper 函數(shù)也可以對(duì)被裝飾函數(shù)的參數(shù)和返回值進(jìn)行修改,從而實(shí)現(xiàn)更加靈活的功能擴(kuò)展。
以下是一個(gè)示例代碼:
def memoize(func): cache = {} def wrapper(*args): if args in cache: return cache[args] else: result = func(*args) cache[args] = result return result return wrapper @memoize def fibonacci(n): if n < 2: return n else: return fibonacci(n-1) + fibonacci(n-2)
在上面的代碼中,memoize 裝飾器用于實(shí)現(xiàn)函數(shù)的緩存,可以避免重復(fù)計(jì)算。在上面的例子中,fibonacci 函數(shù)是一個(gè)遞歸函數(shù),通過(guò) @memoize 裝飾器來(lái)實(shí)現(xiàn)緩存。
Python中的裝飾器可以用于實(shí)現(xiàn)函數(shù)的緩存,其原理是在函數(shù)執(zhí)行前,首先判斷傳入的參數(shù)是否在緩存中已經(jīng)存在對(duì)應(yīng)的計(jì)算結(jié)果,如果存在,則直接返回緩存中的結(jié)果,否則執(zhí)行函數(shù)的計(jì)算過(guò)程,并將計(jì)算結(jié)果保存在緩存中,以便下次直接使用。
通常情況下,緩存會(huì)以一個(gè)字典的形式保存在內(nèi)存中,字典的鍵值對(duì)分別為函數(shù)的參數(shù)和返回值。由于字典的查詢操作復(fù)雜度為O(1),所以可以快速地判斷傳入?yún)?shù)是否存在緩存中,并且快速地從緩存中獲取結(jié)果。同時(shí),在使用緩存時(shí),需要注意緩存的容量大小,以避免占用過(guò)多內(nèi)存的情況發(fā)生。
下面是一個(gè)簡(jiǎn)單的例子,用 Python 的裝飾器實(shí)現(xiàn)函數(shù)的緩存:
def cache(func): memory = {} def wrapper(*args): if args not in memory: memory[args] = func(*args) return memory[args] return wrapper @cache def fib(n): if n <= 1: return n else: return fib(n-1) + fib(n-2) print(fib(10))
在這段代碼中,我們定義了一個(gè) cache 裝飾器,它接受一個(gè)函數(shù)作為參數(shù),并返回一個(gè)包裝函數(shù) wrapper。wrapper 函數(shù)中維護(hù)了一個(gè)字典 memory,用于存儲(chǔ)已經(jīng)計(jì)算過(guò)的結(jié)果。在調(diào)用被裝飾的函數(shù)之前,wrapper 函數(shù)首先檢查是否已經(jīng)計(jì)算過(guò)該參數(shù)的結(jié)果,如果已經(jīng)計(jì)算過(guò),則直接從 memory 字典中返回結(jié)果;否則,調(diào)用被裝飾的函數(shù)進(jìn)行計(jì)算,并將結(jié)果存儲(chǔ)到 memory 字典中,最后返回計(jì)算結(jié)果。
在上面的代碼中,我們使用裝飾器語(yǔ)法 @cache 來(lái)將 fib 函數(shù)進(jìn)行裝飾,這相當(dāng)于執(zhí)行了下面的代碼
fib = cache(fib)
也就是將 fib 函數(shù)作為參數(shù)傳遞給 cache 函數(shù),返回一個(gè)新的函數(shù) wrapper,然后將 fib 變量指向 wrapper 函數(shù)。
最后,我們調(diào)用 fib(10) 函數(shù),由于該函數(shù)已經(jīng)被 cache 裝飾器裝飾,因此 wrapper 函數(shù)會(huì)先檢查 memory 字典中是否已經(jīng)計(jì)算過(guò) fib(10) 的結(jié)果,如果已經(jīng)計(jì)算過(guò),則直接返回計(jì)算結(jié)果;否則,調(diào)用原始的 fib 函數(shù)進(jìn)行計(jì)算,并將計(jì)算結(jié)果存儲(chǔ)到 memory 字典中,最后返回計(jì)算結(jié)果。由于該代碼中的 fib 函數(shù)是一個(gè)遞歸函數(shù),因此 cache 裝飾器可以避免重復(fù)計(jì)算相同的參數(shù),從而提高函數(shù)的執(zhí)行效率。
到此這篇關(guān)于Python 中的裝飾器可以用于實(shí)現(xiàn)函數(shù)的緩存的文章就介紹到這了,更多相關(guān)Python裝飾器實(shí)現(xiàn)緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python與R語(yǔ)言的簡(jiǎn)要對(duì)比
這篇文章主要介紹了Python與R語(yǔ)言的簡(jiǎn)要對(duì)比,小編覺(jué)得還挺不錯(cuò)的,這里分享給大家,需要的朋友可以了解下。2017-11-11matplotlib相關(guān)系統(tǒng)目錄獲取方式小結(jié)
這篇文章主要介紹了matplotlib相關(guān)系統(tǒng)目錄獲取方式小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02使用Numpy讀取CSV文件,并進(jìn)行行列刪除的操作方法
今天小編就為大家分享一篇使用Numpy讀取CSV文件,并進(jìn)行行列刪除的操作方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07使用Python制作一個(gè)數(shù)據(jù)預(yù)處理小工具(多種操作一鍵完成)
這篇文章主要介紹了使用Python制作一個(gè)數(shù)據(jù)預(yù)處理小工具(多種操作一鍵完成),本文通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02?python中字符串的常見(jiàn)操作總結(jié)(二)
這篇文章主要介紹了python中字符串的常見(jiàn)操作,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07詳解在python操作數(shù)據(jù)庫(kù)中游標(biāo)的使用方法
這篇文章主要介紹了在python操作數(shù)據(jù)庫(kù)中游標(biāo)的使用方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11