Python裝飾器結合遞歸原理解析
更新時間:2020年07月02日 10:14:24 作者:JonnyJiang-zh
這篇文章主要介紹了Python裝飾器結合遞歸原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
代碼如下:
import functools def memoize(fn): print('start memoize') known = dict() @functools.wraps(fn) def memoizer(*args): if args not in known: print('memorize %s'%args) # known[args] = fn(*args) for k in known.keys(): print('%s : %s'%(k, known[k]), end = ' ') print() # return known[args] return memoizer @memoize def nsum(n): print('now is %s'%n) assert (n >= 0), 'n must be >= 0' return 0 if n == 0 else n + nsum(n - 1) @memoize def fibonacci(n): assert (n >= 0), 'n must be >= 0' return n if n in (0, 1) else fibonacci(n - 1) + fibonacci(n - 2) if __name__ == '__main__': print(nsum(10)) print(fibonacci(10))
輸出如下:
start memoize
start memoize
memorize 10None
memorize 10None
對比代碼(把注釋的地方去掉后)的輸出:
start memoize start memoize memorize 10 now is 10 memorize 9 now is 9 memorize 8 now is 8 memorize 7 now is 7 memorize 6 now is 6 memorize 5 now is 5 memorize 4 now is 4 memorize 3 now is 3 memorize 2 now is 2 memorize 1 now is 1 memorize 0 now is 0 (0,) : 0 (0,) : 0 (1,) : 1 (0,) : 0 (1,) : 1 (2,) : 3 (0,) : 0 (1,) : 1 (2,) : 3 (3,) : 6 (0,) : 0 (1,) : 1 (2,) : 3 (3,) : 6 (4,) : 10 (0,) : 0 (1,) : 1 (2,) : 3 (3,) : 6 (4,) : 10 (5,) : 15 (0,) : 0 (1,) : 1 (2,) : 3 (3,) : 6 (4,) : 10 (5,) : 15 (6,) : 21 (0,) : 0 (1,) : 1 (2,) : 3 (3,) : 6 (4,) : 10 (5,) : 15 (6,) : 21 (7,) : 28 (0,) : 0 (1,) : 1 (2,) : 3 (3,) : 6 (4,) : 10 (5,) : 15 (6,) : 21 (7,) : 28 (8,) : 36 (0,) : 0 (1,) : 1 (2,) : 3 (3,) : 6 (4,) : 10 (5,) : 15 (6,) : 21 (7,) : 28 (8,) : 36 (9,) : 45 (0,) : 0 (1,) : 1 (2,) : 3 (3,) : 6 (4,) : 10 (5,) : 15 (6,) : 21 (7,) : 28 (8,) : 36 (9,) : 45 (10,) : 55
通過取消注釋的對比,可以得到如下結論:
- 裝飾器memoize實際上對于函數(shù)nsum()只執(zhí)行了第一次加載的時候的預處理,然后就是nsum = memoizer。
- 裝飾器的實質(zhì)是通過functools.wraps(fn)獲得函數(shù)的名字,便于nsum.__name__ ==nsum,并將參數(shù)傳至memoize(*args),也就是*args。
- 裝飾器通過memory(),和外面的裝飾器獲得的函數(shù),在內(nèi)部對函數(shù)進行功能改造。在上例子中,通過known[args] = fn(*args)先執(zhí)行fn函數(shù),即上例子中nsum(10),然后就進入遞歸,t同時調(diào)用memoizer()和nsum()函數(shù)10次,且先memoizer再nsum,而且每次都在``known[args] = fn(*args)`進入遞歸,也就是每次nsum的執(zhí)行,故,對于為什么打印konwn中的元素是集中在一起的解釋就知道了,到了n == 0,才跳出遞歸,故,known的第一個元素是0,然后就循環(huán)往復。
- 最后,其實,遞歸函數(shù)執(zhí)行的是fn(*args),即nsum()。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Django靜態(tài)文件配置request對象方法ORM操作講解
這篇文章主要為大家介紹了Django靜態(tài)文件配置request對象方法ORM操作,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09tensorflow 1.X遷移至tensorflow2 的代碼寫法
本文主要介紹了tensorflow 1.X遷移至tensorflow2 的代碼寫法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12python實現(xiàn)在多維數(shù)組中挑選符合條件的全部元素
今天小編就為大家分享一篇python實現(xiàn)在多維數(shù)組中挑選符合條件的全部元素,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11用Python實現(xiàn)換行符轉(zhuǎn)換的腳本的教程
這篇文章主要介紹了用Python實現(xiàn)換行符轉(zhuǎn)換的腳本的教程,代碼非常簡單,包括一個對操作說明的功能的實現(xiàn),需要的朋友可以參考下2015-04-04