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 相关文章推荐
py中的目录与文件判别代码
Jul 16 Python
python为tornado添加recaptcha验证码功能
Feb 26 Python
Hadoop中的Python框架的使用指南
Apr 22 Python
python 性能提升的几种方法
Jul 15 Python
微信跳一跳python辅助脚本(总结)
Jan 11 Python
在python中实现强制关闭线程的示例
Jan 22 Python
python 获取毫秒数,计算调用时长的方法
Feb 20 Python
python pytest进阶之xunit fixture详解
Jun 27 Python
wxpython实现按钮切换界面的方法
Nov 19 Python
python求绝对值的三种方法小结
Dec 04 Python
Python 2种方法求某个范围内的所有素数(质数)
Jan 31 Python
在Matplotlib图中插入LaTex公式实例
Apr 17 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继承的一个应用
2011/09/06 PHP
PHP使用get_headers函数判断远程文件是否存在的方法
2014/11/28 PHP
dojo 之基础篇(二)之从服务器读取数据
2007/03/24 Javascript
JavaScript URL参数读取改进版
2009/01/16 Javascript
用jquery实现等比例缩放图片效果插件
2010/07/24 Javascript
如何使用Javascript正则表达式来格式化XML内容
2013/07/04 Javascript
jquery 判断滚动条到达了底部和顶端的方法
2014/04/02 Javascript
javascript动态修改Li节点值的方法
2015/01/20 Javascript
实例代码详解jquery.slides.js
2015/11/16 Javascript
ECMAScript6快速入手攻略
2016/07/18 Javascript
JavaScript之cookie技术详解
2016/11/18 Javascript
javascript中href和replace的比较(详解)
2016/11/25 Javascript
新闻上下滚动jquery 超简洁(必看篇)
2017/01/21 Javascript
JavaScript实现前端实时搜索功能
2020/03/26 Javascript
ionic 3.0+ 项目搭建运行环境的教程
2017/08/09 Javascript
D3.js实现简洁实用的动态仪表盘的示例
2018/04/04 Javascript
解决Vue在封装了Axios后手动刷新页面拦截器无效的问题
2018/11/08 Javascript
Three.js实现3D机房效果
2018/12/30 Javascript
python xml解析实例详解
2016/11/14 Python
python实现简易动态时钟
2018/11/19 Python
Python设计模式之简单工厂模式实例详解
2019/01/22 Python
python 魔法函数实例及解析
2019/09/25 Python
Python cookie的保存与读取、SSL讲解
2020/02/17 Python
python退出循环的方法
2020/06/18 Python
python 调用API接口 获取和解析 Json数据
2020/09/28 Python
英国Boots旗下太阳镜网站:Boots Designer Sunglasses
2018/07/07 全球购物
BIFFI美国站:意大利BIFFI BOUTIQUES豪华多品牌时装零售公司
2020/02/11 全球购物
2014学雷锋活动总结
2014/03/09 职场文书
安全生产知识竞赛活动总结
2014/07/07 职场文书
化学专业毕业生求职信
2014/07/28 职场文书
好的促销活动方案
2014/08/21 职场文书
2014年审计工作总结
2014/11/17 职场文书
管理人员岗位职责
2015/02/14 职场文书
综合办公室主任岗位职责
2015/04/01 职场文书
外科护士长工作总结
2015/08/12 职场文书
CSS实现九宫格布局(自适应)的示例代码
2022/02/12 HTML / CSS