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绘制人人网好友关系图示例
Apr 01 Python
python创建关联数组(字典)的方法
May 04 Python
Python常用的文件及文件路径、目录操作方法汇总介绍
May 21 Python
Python实现对excel文件列表值进行统计的方法
Jul 25 Python
Python正则获取、过滤或者替换HTML标签的方法
Jan 28 Python
python模块之time模块(实例讲解)
Sep 13 Python
恢复百度云盘本地误删的文件脚本(简单方法)
Oct 21 Python
10个Python小技巧你值得拥有
Sep 29 Python
Python + OpenCV 实现LBP特征提取的示例代码
Jul 11 Python
Python3基本输入与输出操作实例分析
Feb 14 Python
Python应用自动化部署工具Fabric原理及使用解析
Nov 30 Python
Python实现位图分割的效果
Nov 20 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 filter_var() 函数 Filter 函数
2012/04/25 PHP
php实现的获取网站备案信息查询代码(360)
2013/09/23 PHP
php从给定url获取文件扩展名的方法
2015/03/14 PHP
js禁止小键盘输入数字功能代码
2011/08/01 Javascript
更换select下拉菜单背景样式的实现代码
2011/12/20 Javascript
给页面渲染时间加速 干掉Dom Level 0 Event
2012/12/19 Javascript
JS中引用百度地图并将百度地图的logo和信息去掉
2013/09/29 Javascript
js实现网页标题栏闪烁提示效果实例分析
2014/11/20 Javascript
JS制作简单的三级联动
2015/03/18 Javascript
JavaScript中三个等号和两个等号你了解多少
2017/07/04 Javascript
Vue单文件组件基础模板小结
2017/08/10 Javascript
javascript+html5+css3自定义弹出窗口效果
2017/10/26 Javascript
使用命令行工具npm新创建一个vue项目的方法
2017/12/27 Javascript
js 计算图片内点个数的示例代码
2019/04/04 Javascript
javascript实现遮罩层动态效果实例
2019/05/14 Javascript
vue滚动固定顶部及修改样式的实例代码
2019/05/30 Javascript
nodejs中各种加密算法的实现详解
2019/07/11 NodeJs
webpack常用配置总览(小结)
2019/11/18 Javascript
angular inputNumber指令输入框只能输入数字的实现
2019/12/03 Javascript
easyUI使用分页过滤器对数据进行分页操作实例分析
2020/06/01 Javascript
Python编程实现线性回归和批量梯度下降法代码实例
2018/01/04 Python
Python二叉树的遍历操作示例【前序遍历,中序遍历,后序遍历,层序遍历】
2018/12/24 Python
Flask配置Cors跨域的实现
2019/07/12 Python
Django组件content-type使用方法详解
2019/07/19 Python
Python Tkinter图形工具使用方法及实例解析
2020/06/15 Python
anaconda3安装及jupyter环境配置全教程
2020/08/24 Python
HTML5高仿微信聊天、微信聊天表情|对话框|编辑器功能
2018/04/23 HTML / CSS
Expedia韩国官网:亚洲发展最快的在线旅游门户网站
2018/02/26 全球购物
建筑装饰学院室内设计专业个人自我评价
2013/12/07 职场文书
小学门卫岗位职责
2013/12/17 职场文书
《日月潭》教学反思
2014/02/28 职场文书
《开国大典》教学反思
2014/04/19 职场文书
基层党员群众路线整改措施及努力方向
2014/10/28 职场文书
商场广播稿范文
2015/08/19 职场文书
2016年基层党组织创先争优承诺书
2016/03/25 职场文书
《帝国时代4》赛季预告 新增内容编译器可创造地图
2022/04/03 其他游戏