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中使用插入排序算法的简单分析与代码示例
May 04 Python
python开发简易版在线音乐播放器
Mar 03 Python
利用selenium 3.7和python3添加cookie模拟登陆的实现
Nov 20 Python
浅析python打包工具distutils、setuptools
Apr 20 Python
解决pandas无法在pycharm中使用plot()方法显示图像的问题
May 24 Python
python爬虫的一个常见简单js反爬详解
Jul 09 Python
Python利用Scrapy框架爬取豆瓣电影示例
Jan 17 Python
keras获得某一层或者某层权重的输出实例
Jan 24 Python
python中if及if-else如何使用
Jun 02 Python
Python环境管理virtualenv&virtualenvwrapper的配置详解
Jul 01 Python
解决python 在for循环并且pop数组的时候会跳过某些元素的问题
Dec 11 Python
python开发制作好看的时钟效果
May 02 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 服务器调试 Zend Debugger 的安装教程
2009/09/25 PHP
PHP 关于访问控制的和运算符优先级介绍
2013/07/08 PHP
ThinkPHP进程计数类Process用法实例详解
2015/09/25 PHP
PHP进阶学习之Geo的地图定位算法详解
2019/06/19 PHP
php5.3/5.4/5.5/5.6/7常见新增特性汇总整理
2020/02/27 PHP
PHP执行linux命令6个函数代码实例
2020/11/24 PHP
javascript 有趣而诡异的数组
2009/04/06 Javascript
用nodejs访问ActiveX对象,以操作Access数据库为例。
2011/12/15 NodeJs
JavaScript省市联动实现代码
2014/02/15 Javascript
jQuery简单实现上下,左右滑动的方法
2016/06/01 Javascript
AngularJs  Using $location详解及示例代码
2016/09/02 Javascript
js中数组插入、删除元素操作的方法
2017/02/15 Javascript
值得分享和收藏的xmlplus组件学习教程
2017/05/05 Javascript
Angular2搜索和重置按钮过场动画
2017/05/24 Javascript
AngularJS实用基础知识_入门必备篇(推荐)
2017/07/10 Javascript
js经验分享 JavaScript反调试技巧
2018/03/10 Javascript
使用Vue-cli3.0创建的项目 如何发布npm包
2019/10/10 Javascript
Vue 实现把表单form数据 转化成json格式的数据
2019/10/29 Javascript
vue keep-alive 动态删除组件缓存的例子
2019/11/04 Javascript
Vue实现手机号、验证码登录(60s禁用倒计时)
2020/12/19 Vue.js
Numpy之reshape()使用详解
2019/12/26 Python
python闭包与引用以及需要注意的陷阱
2020/09/18 Python
HTML5之SVG 2D入门7—SVG元素的重用与引用
2013/01/30 HTML / CSS
澳洲健康食品网上商店:Aussie Health Products
2018/06/15 全球购物
Tenstickers法国:墙贴和装饰贴纸
2019/08/26 全球购物
专科毕业生求职简历的自我评价
2013/10/12 职场文书
机关副主任个人四风问题整改措施
2014/09/26 职场文书
未婚证明书模板
2014/10/08 职场文书
走群众路线剖析材料
2014/10/09 职场文书
党的群众路线教育实践活动学习笔记范文
2014/11/06 职场文书
幼儿园教师节活动总结
2015/03/23 职场文书
工会文体活动总结
2015/05/07 职场文书
食堂卫生管理制度
2015/08/04 职场文书
实验室安全管理制度
2015/08/05 职场文书
Django 实现jwt认证的示例
2021/04/30 Python
ssh服务器拒绝了密码 请再试一次已解决(亲测有效)
2022/08/14 Servers