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出现"IndentationError: unexpected indent"错误解决办法
Oct 15 Python
Python编程实现粒子群算法(PSO)详解
Nov 13 Python
Python实现翻转数组功能示例
Jan 12 Python
python使用matplotlib画饼状图
Sep 25 Python
nohup后台启动Python脚本,log不刷新的解决方法
Jan 14 Python
Python脚本利用adb进行手机控制的方法
Jul 08 Python
python实现银行管理系统
Oct 25 Python
pygame实现贪吃蛇游戏(上)
Oct 29 Python
Django values()和value_list()的使用
Mar 31 Python
Python爬虫谷歌Chrome F12抓包过程原理解析
Jun 04 Python
Python通过递归函数输出嵌套列表元素
Oct 15 Python
教你怎么用Python处理excel实现自动化办公
Apr 30 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
了解Joomla 这款来自国外的php网站管理系统
2010/03/11 PHP
Php获取金书网的书名的实现代码
2010/06/11 PHP
php 操作调试的方法
2012/07/12 PHP
php数组(array)输出的三种形式详解
2013/06/05 PHP
PHP小白必须要知道的php基础知识(超实用)
2017/10/10 PHP
腾讯与新浪的通过IP地址获取当前地理位置(省份)的接口
2010/07/26 Javascript
基于Jquery 解决Ajax请求的页面 浏览器后退前进功能,页面刷新功能实效问题
2010/12/11 Javascript
jQuery find和children方法使用
2011/01/31 Javascript
纯JS实现根据CSS的class选择DOM
2014/03/22 Javascript
判断字符串的长度(优化版)中文占两个字符
2014/10/30 Javascript
JS+CSS实现简单滑动门(滑动菜单)效果
2015/09/19 Javascript
JS使用JSON作为参数实例分析
2016/06/23 Javascript
js实现砖头在页面拖拉效果
2020/11/20 Javascript
Vue实现购物车功能
2017/04/27 Javascript
angularJS模态框$modal实例代码
2017/05/27 Javascript
如何在Vue.js中实现标签页组件详解
2019/01/02 Javascript
Vue表单控件绑定图文详解
2019/02/11 Javascript
中级前端工程师必须要掌握的27个JavaScript 技巧(干货总结)
2019/09/23 Javascript
js实现时间日期校验
2020/05/26 Javascript
Python标准库与第三方库详解
2014/07/22 Python
python比较两个列表大小的方法
2015/07/11 Python
Python简单实现网页内容抓取功能示例
2018/06/07 Python
Python3爬虫学习入门教程
2018/12/11 Python
详解Python基础random模块随机数的生成
2019/03/23 Python
python的faker库用法
2019/11/28 Python
浅谈Python中的生成器和迭代器
2020/06/19 Python
浅谈keras中的后端backend及其相关函数(K.prod,K.cast)
2020/06/29 Python
Python脚本调试工具安装过程
2021/01/11 Python
公司拓展活动方案
2014/02/13 职场文书
学雷锋演讲稿汇总
2014/05/10 职场文书
小学教师暑期培训方案
2014/08/28 职场文书
副乡长群众路线教育实践活动个人对照检查材料
2014/09/19 职场文书
运动会广播稿150字(9篇)
2014/09/20 职场文书
交通事故被告代理词
2015/05/23 职场文书
话题作文之诚信
2019/11/28 职场文书
Python Django / Flask如何使用Elasticsearch
2022/04/19 Python