Python装饰器结合递归原理解析


Posted in Python onJuly 02, 2020

代码如下:

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 10

None
memorize 10

None

对比代码(把注释的地方去掉后)的输出:

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()。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python使用cookielib库示例分享
Mar 03 Python
对于Python装饰器使用的一些建议
Jun 03 Python
python 默认参数问题的陷阱
Feb 29 Python
Python2.7+pytesser实现简单验证码的识别方法
Dec 29 Python
python批量下载网站马拉松照片的完整步骤
Dec 05 Python
python 正则表达式贪婪模式与非贪婪模式原理、用法实例分析
Oct 14 Python
python中使用input()函数获取用户输入值方式
May 03 Python
Python导入数值型Excel数据并生成矩阵操作
Jun 09 Python
python使用QQ邮箱实现自动发送邮件
Jun 22 Python
python使用opencv resize图像不进行插值的操作
Jul 05 Python
10款最佳Python开发工具推荐,每一款都是神器
Oct 15 Python
python中uuid模块实例浅析
Dec 29 Python
Python OpenCV读取中文路径图像的方法
Jul 02 #Python
keras.utils.to_categorical和one hot格式解析
Jul 02 #Python
python 使用多线程创建一个Buffer缓存器的实现思路
Jul 02 #Python
浅谈keras中的keras.utils.to_categorical用法
Jul 02 #Python
Python使用OpenPyXL处理Excel表格
Jul 02 #Python
解决keras GAN训练是loss不发生变化,accuracy一直为0.5的问题
Jul 02 #Python
解决keras,val_categorical_accuracy:,0.0000e+00问题
Jul 02 #Python
You might like
PHP网页游戏学习之Xnova(ogame)源码解读(一)
2014/06/23 PHP
PHP中substr_count()函数获取子字符串出现次数的方法
2016/01/07 PHP
AJAX的使用方法详解
2017/04/29 PHP
javascript 鼠标拖动图标技术
2010/02/07 Javascript
NodeJS学习笔记之Connect中间件应用实例
2015/01/27 NodeJs
js+html5通过canvas指定开始和结束点绘制线条的方法
2015/06/05 Javascript
原生javascript 学习之js变量全面了解
2016/07/14 Javascript
基于Layer+jQuery的自定义弹框
2020/05/26 Javascript
jquery与ajax获取特殊字符实例详解
2017/01/08 Javascript
详解bootstrap的modal-remote两种加载方式【强化】
2017/01/27 Javascript
利用imgareaselect辅助后台实现图片上传裁剪
2017/03/02 Javascript
jQuery实现动态生成表格并为行绑定单击变色动作的方法
2017/04/17 jQuery
JS奇技之利用scroll来监听resize详解
2017/06/15 Javascript
Vue.js中关于侦听器(watch)的高级用法示例
2018/05/02 Javascript
NestJs 静态目录配置详解
2019/03/12 Javascript
JavaScript实现简单进度条效果
2020/03/25 Javascript
让你30分钟快速掌握vue3教程
2020/10/26 Javascript
[03:18]DOTA2亚洲邀请赛小组赛第一日 RECAP赛事回顾
2015/01/30 DOTA
python快速查找算法应用实例
2014/09/26 Python
Python中使用摄像头实现简单的延时摄影技术
2015/03/27 Python
python 字符串和整数的转换方法
2018/06/25 Python
python调用opencv实现猫脸检测功能
2019/01/15 Python
Python读取YAML文件过程详解
2019/12/30 Python
python实现查找所有程序的安装信息
2020/02/18 Python
python中的列表和元组区别分析
2020/12/30 Python
大学毕业通用个人的求职信
2013/12/08 职场文书
建筑文秘专业个人求职信范文
2013/12/28 职场文书
职业道德模范事迹材料
2014/08/24 职场文书
群众路线自我剖析材料
2014/10/08 职场文书
2014年作风建设心得体会
2014/10/22 职场文书
自我检讨书范文
2015/01/28 职场文书
2015年部门工作总结范文
2015/03/31 职场文书
2015年建筑工程工作总结
2015/05/13 职场文书
2015年征兵工作总结
2015/07/23 职场文书
2016秋季运动会前导词
2015/11/25 职场文书
python接口测试返回数据为字典取值方式
2022/02/12 Python