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编写脚本获取手机当前应用apk的信息
Jul 21 Python
python对字典进行排序实例
Sep 25 Python
python连接oracle数据库实例
Oct 17 Python
python中的装饰器详解
Apr 13 Python
pandas.DataFrame 根据条件新建列并赋值的方法
Apr 08 Python
Python定时任务随机时间执行的实现方法
Aug 14 Python
关于PyTorch 自动求导机制详解
Aug 18 Python
python 实现快速生成连续、随机字母列表
Nov 28 Python
python画图常规设置方式
Mar 05 Python
在Python3.74+PyCharm2020.1 x64中安装使用Kivy的详细教程
Aug 07 Python
Python ConfigParser模块的使用示例
Oct 12 Python
python全栈开发语法总结
Nov 22 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 4.2书写安全的脚本
2006/10/09 PHP
php HandlerSocket的使用
2011/05/02 PHP
PHP+javascript制作带提示的验证码源码分享
2014/05/28 PHP
PHP7 list() 函数修改
2021/03/09 PHP
javascript静态的url如何传递
2007/05/03 Javascript
offsetParent 算法分析
2010/04/05 Javascript
基于jQuery中对数组进行操作的方法
2013/04/16 Javascript
Jquery中扩展方法extend使用技巧
2014/08/24 Javascript
轻松实现javascript图片轮播特效
2016/01/13 Javascript
基于vue实现多引擎搜索及关键字提示
2017/03/16 Javascript
bootstrap suggest下拉框使用详解
2017/04/10 Javascript
jq.ajax+php+mysql实现关键字模糊查询(示例讲解)
2018/01/02 Javascript
VSCode插件安装完成后的配置(常用配置)
2020/08/24 Javascript
Vant 在vue-cli 4.x中按需加载操作
2020/11/05 Javascript
对于Python中RawString的理解介绍
2016/07/07 Python
python 出现SyntaxError: non-keyword arg after keyword arg错误解决办法
2017/02/14 Python
python做量化投资系列之比特币初始配置
2018/01/23 Python
Python实现获取nginx服务器ip及流量统计信息功能示例
2018/05/18 Python
python匿名函数用法实例分析
2019/08/03 Python
python3 反射的四种基本方法解析
2019/08/26 Python
Python读取实时数据流示例
2019/12/02 Python
将python文件打包exe独立运行程序方法详解
2020/02/12 Python
python实现爱奇艺登陆密码RSA加密的方法示例详解
2020/05/27 Python
前端canvas水印快速制作(附完整代码)
2019/09/19 HTML / CSS
澳大利亚儿童和婴儿产品在线商店:Lime Tree Kids
2017/10/05 全球购物
莫斯科绝对前卫最秘密的商店:SVMoscow
2017/10/23 全球购物
美国潜水装备、水肺潜水和浮潜设备商店:Leisure Pro
2018/08/08 全球购物
J2EE中的容器都包括哪些
2013/08/21 面试题
物流管理专业应届生求职信
2013/11/21 职场文书
计算机学生的自我评价分享
2014/02/18 职场文书
夜不归宿检讨书
2014/02/25 职场文书
大学四年个人自我小结
2014/03/05 职场文书
幼儿园中班区域活动总结
2014/07/09 职场文书
县政协领导班子群众路线教育实践活动四风问题整改方案
2014/10/26 职场文书
2014年银行柜员工作总结
2014/11/12 职场文书
vue2的 router在使用过程中遇到的一些问题
2022/04/13 Vue.js