Python装饰器结合递归原理解析
作者:JonnyJiang-zh 发布时间:2023-07-13 22:24:00
标签: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实际上对于函数nsum()只执行了第一次加载的时候的预处理,然后就是nsum = memoizer。
装饰器的实质是通过functools.wraps(fn)获得函数的名字,便于nsum.__name__ ==nsum,并将参数传至memoize(*args),也就是*args。
装饰器通过memory(),和外面的装饰器获得的函数,在内部对函数进行功能改造。在上例子中,通过known[args] = fn(*args)先执行fn函数,即上例子中nsum(10),然后就进入递归,t同时调用memoizer()和nsum()函数10次,且先memoizer再nsum,而且每次都在``known[args] = fn(*args)`进入递归,也就是每次nsum的执行,故,对于为什么打印konwn中的元素是集中在一起的解释就知道了,到了n == 0,才跳出递归,故,known的第一个元素是0,然后就循环往复。
最后,其实,递归函数执行的是fn(*args),即nsum()。
来源:https://www.cnblogs.com/JonnyJiang-zh/p/13216770.html
0
投稿
猜你喜欢
- 错误的代码①d = {'a':1, 'b':0, 'c':1, 'd':0}
- 前提官网上提供了 Mac 和 Windows 上的安装包和 Linux 上安装需要的源码。下载地址如下:https://www.python
- Python之Selenium自动化爬虫0.介绍Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,Seleniu
- Tensorflow数据读取有三种方式:Preloaded data: 预加载数据Feeding: Python产生数据,再把数据喂给后端。
- 如下所示:# Seed random number generatornp.random.seed(42)# Compute mean no
- import timenow_time = time.time()print(now_time)结果是1594
- 遍历字典: keys() 、values() 、items()1. xxx.keys() : 返回字典的所有的key 返回一个序列,序列中保
- interfaceGo语言里面设计最精妙的应该算interface,它让面向对象,内容组织实现非常的方便,当你看完这一章,你就会被inter
- 试一试这个办法:struserlist = struserlist & "<
- 1.whl包whl格式本质上是一个压缩包,里面包含了py文件,以及经过编译的pyd文件。使得可以在不具备编译环境的情况下,选择适合自己的py
- 原文地址:30 Days of Mootools 1.2 Tutorials - Day 5 - Event HandlingMooTool
- Python自身作为一门编程语言,它有多种实现。这里的实现指的是符合Python语言规范的Python解释程序以及标准库等。这些实现虽然实现
- 写了个多层感知器,用bp梯度下降更新,拟合正弦曲线,效果凑合。# -*- coding: utf-8 -*-import numpy as
- 众所周知,程序在启动后,各个程序文件都会被加载到内存中,这样如果程序文本再次变化,对当前程序的运行没有影响,这对程序是一种保护。但是,对于像
- 本文实例讲述了python实现合并两个数组的方法。分享给大家供大家参考。具体如下:python合并两个数组,将两个数组连接成一个数组,例如,
- “正则表达式”对象,我们就可以非常方便的对各种数据进行合法性的校验了。首先,让我们来了解一下究竟什么
- 方法一:使用装饰器装饰器维护一个字典对象instances,缓存了所有单例类,只要单例不存在则创建,已经存在直接返回该实例对象。def si
- 为cd2sc.com网站功能而开发,代码为本人原创,生成速度一般。 (出于众所周知的原因,涉及到数据库的数据字段名称做了改动,并且为了代码明
- Python中为了方便程序直接生成exe文件,它存在一个pyinstaller库,使用这个库可以直接将.py程序生成exe文件。这个命令不是
- 如下所示:# coding: utf-8import paramikoimport MySQLdbdef main(): connectio