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中利用Pandas库处理大数据的简单介绍
Apr 07 Python
python使用Queue在多个子进程间交换数据的方法
Apr 18 Python
利用Python实现简单的相似图片搜索的教程
Apr 23 Python
python正则表达式re之compile函数解析
Oct 25 Python
Python实现获取邮箱内容并解析的方法示例
Jun 16 Python
python for 循环获取index索引的方法
Feb 01 Python
PyQt5实现简易电子词典
Jun 25 Python
Python用Try语句捕获异常的实例方法
Jun 26 Python
对python中不同模块(函数、类、变量)的调用详解
Jul 16 Python
python实现视频读取和转化图片
Dec 10 Python
python 下载文件的几种方式分享
Apr 07 Python
Python预测分词的实现
Jun 18 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
一拳超人中怪人协会钦定! S级别最强四人!
2020/03/02 日漫
从手册去理解分析PHP session机制
2011/07/17 PHP
php+ajax实现无刷新分页的方法
2014/11/04 PHP
PHP中使用GD库创建圆形饼图的例子
2014/11/19 PHP
php中目录操作opendir()、readdir()及scandir()用法示例
2019/06/08 PHP
PHP+Mysql分布式事务与解决方案深入理解
2021/02/27 PHP
Javascript SHA-1:Secure Hash Algorithm
2006/12/20 Javascript
jQuery中阻止冒泡事件的方法介绍
2014/04/12 Javascript
node.js中的fs.chownSync方法使用说明
2014/12/16 Javascript
Javascript核心读书有感之词法结构
2015/02/01 Javascript
js验证真实姓名与身份证号是否匹配
2015/10/13 Javascript
php基于redis处理session的方法
2016/03/14 Javascript
基于JavaScript实现添加到购物车效果附源码下载
2016/08/22 Javascript
Jquery组件easyUi实现手风琴(折叠面板)示例
2016/08/23 Javascript
基于jQuery的select下拉框选择触发事件实例分析
2016/11/18 Javascript
JS代码实现电脑配置检测功能
2018/03/21 Javascript
vue2.0 自定义组件的方法(vue组件的封装)
2018/06/05 Javascript
JS+H5 Canvas实现时钟效果
2018/07/20 Javascript
jQuery实现点击旋转,再点击恢复初始状态动画效果示例
2018/12/11 jQuery
ES6知识点整理之函数数组参数的默认值及其解构应用示例
2019/04/17 Javascript
vue router 跳转时打开新页面的示例方法
2019/07/28 Javascript
python获取豆瓣电影简介代码分享
2014/01/16 Python
Python中给List添加元素的4种方法分享
2014/11/28 Python
利用Python为iOS10生成图标和截屏
2016/09/24 Python
使用Python实现在Windows下安装Django
2018/10/17 Python
如何用Python来理一理红楼梦里的那些关系
2019/08/14 Python
django框架F&Q 聚合与分组操作示例
2019/12/12 Python
Python使用py2neo操作图数据库neo4j的方法详解
2020/01/13 Python
django配置app中的静态文件步骤
2020/03/27 Python
世界上最大的专业美容用品零售商:Sally Beauty
2017/07/02 全球购物
戴森比利时官方网站:Dyson BE
2020/10/03 全球购物
小学生环保标语
2014/06/13 职场文书
卖车协议书范本4篇
2014/10/01 职场文书
2016年公司“3.12”植树节活动总结
2016/03/16 职场文书
Nginx+Tomcat实现负载均衡、动静分离的原理解析
2021/03/31 Servers
uniapp开发小程序的经验总结
2021/04/08 Javascript