力扣上看到一道题:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

  使用普通递归解决,超出时间限制:

  添加lru_cache之后,缩短了时间

lru_cache的解释如下:

现在你已经看到了如何自己实现一个memoization函数,我会告诉你,你可以使用Python的functools.lru_cache装饰器来获得相同的结果,以增加方便性。

我最喜欢Python的原因之一就是它的语法的简洁和美丽与它的哲学的美丽和简单性并行不悖。Python被称作“内置电池(batteries included)”,这意味着Python捆绑了大量常用的库和模块,这些只需要一个import声明!

我发现functools.lru_cache是一个很好的例子。lru_cache装饰器是Python标准库实现的易于使用的记忆功能。一旦你认识到什么时候使用lru_cache,你只需几行代码就可以快速加快你的应用程序。

我们再来看看我们的斐波那契数列示例。这一次,我会告诉你如何使用functools.lru_cache装饰器添加记忆:

请注意我给lru_cache传递的maxsize参数是同时来限制存储在缓存中的项目数量。

我再一次使用该timeit模块来运行一个简单的基准测试,以便了解这种优化对性能的影响:

您可能想知道,为什么我们这次能够以更快的速度获得第一次运行的结果。第一次运行缓存不应该是 “冻结”的吗?

不同的是,在这个例子中,我在函数定义的时候使用了@lru_cache装饰器。这意味着这次递归调用fibonacci也在缓存中查找。

通过@lru_cache装饰器装饰fibonacci函数,我基本上把它变成了一个动态编程解决方案,每个子问题只需要存储一次子问题解决方案,并在下次尝试解决相同问题时从缓存中查找结果。

这只是一个例子——但我相信你开始能够看到使用memoization装饰器的美丽和强大,并且开始意识到实现一个动态算法能够带来多大的好处。

为什么你应该喜欢 functools.lru_cache

一般来说,由functools.lru_cache实现的Python的memoization比我们的专用memoize函数更全面,就像你在CPython源代码中看到的一样。

例如,它提供了一个方便的功能,允许您使用cache_info方法检索缓存统计信息:

再一次,正如你在CacheInfo输出中看到的那样,Python的lru_cache记住了递归调用fibonacci。当我们查看memoized函数的缓存信息时,您会发现为什么它在第一次运行时比我们的版本更快——缓存命中了34次。

正如我之前所暗示的,functools.lru_cache还允许您使用maxsize参数限制缓存结果的数量。通过设置maxsize=None你可以强制缓存是无界的,我通常会反对这样做。

还有一个typed布尔参数可以设置为True告诉缓存,不同类型的函数参数应该分开缓存。例如,fibonacci(35)和fibonacci(35.0)将被视为产生截然不同结果的不同调用。

另一个有用的功能是可以随时使用cache_clear方法重置结果缓存:

如果您想了解更多关于使用lru_cache装饰器的复杂信息,我建议您参考Python标准库文档。

总之,你永远不需要推出自己的记忆功能。Python的内置方法lru_cache是易于使用的,更全面和经过测试的。

缓存注意事项——什么是可以被记忆的?

理想情况下,您将要记忆确定性的函数。

这deterministic_adder是一个确定性函数,因为它总是会为相同的一对参数返回相同的结果。例如,如果您将2和3传入该函数,它将始终返回5。

将此行为与以下非确定性函数进行比较:

这个函数是不确定的,因为它对于一个给定的输入的输出会根据星期几而变化:如果你在星期一运行这个函数,缓存将在一周中的任何一天返回陈旧的数据。

一般来说,我发现任何更新记录或返回随时间变化的信息的函数对于记忆都是不好的选择。

或者,正如Phil Karlton所说:

计算机科学只有两件难事:缓存失效和命名事物。

——Phil Karlton

Python中的记忆:快速总结

在这篇Python教程中,您看到了memoization如何通过基于提供给它的参数缓存输出来优化函数。

一旦你记忆一个函数,它将只为你调用的每一组参数计算一次输出。第一次调用之后的每次调用都将快速从缓存中检索出来。

您看到了如何从头开始编写自己的memoization装饰器,以及为什么在生产代码中您可能想要用Python内置的lru_cache:

记忆是一种软件优化技术,它根据参数存储返回函数调用的结果。

如果你的代码符合某个标准,memoization可以是一个很好的方法来加快你的应用程序。

您可以从Python标准库中导入一个全面的memoization函数,functools模块中的lru_cache。

functiils.lru_cache缩短递归时间的更多相关文章

  1. 用Redis打造URL缩短服务

    此文章的英文版本已首发于 CodeProject : Building a simple URL shorten service with Redis 阅读文章之前,我建议你先下载源码,一边看文章,一 ...

  2. 如何缩短SQL Server 的启动时间

    将/nosplash添加到SQLServer Manageement Studio的快捷方式可以缩短启动时间.为此,右击SSMS快捷方式(位于你的桌面上.start菜单中或任务栏中)并选择Proper ...

  3. Bitly缩短网址服务 - Blog透视镜

    网站的网址过长或是含有非英文或数字符号,会导致在BBS或者微网志中分享给好友时,产生很多的不方便,Bitly是个缩短网址服务的网站,提供1个短网址转向指定到长网址,免费使用且提供统计报表,例如本篇文章 ...

  4. TinyURL缩短网址服务 - Blog透视镜

    TinyURL是个缩短网址服务的网站,提供1个短网址转向指定到长网址,像是杂志书籍中若有网址太长,也都会用TinyURL来缩短网址,例如本篇文章:http://blog.openyu.org/2014 ...

  5. Google谷歌推出goo.gl缩短网址服务 - Blog透视镜

    Blog部落格文章的网址,例如本篇文章:http://blog.openyu.org/2014/01/google-goo.gl.html,通常都很冗长,分享到社群网站上,容易使得讯息内容过多,同时也 ...

  6. DeNA/上海纵游通过使用AWS大量缩短新款游戏和服务的上线时间

    关于DeNA/上海纵游 DeNA 创立于1999年,是世界率先的网络服务公司,业务涵盖社交游戏.电子商务等领域.DeNA总部设于东京,现已于京证券交易所上市(交易代码:2432),在中国.美国.新加坡 ...

  7. Redis打造URL缩短服务

    用Redis打造URL缩短服务   此文章的英文版本已首发于 CodeProject : Building a simple URL shorten service with Redis 阅读文章之前 ...

  8. 缩短url-url短地址链接

    之前给合作方二维码时隐藏的url过长,导致合作方提出在打印的时候打印不出来的问题,要求url长度在50字节内,所以写了缩短url功能. var url = string.Format("{0 ...

  9. 安装Django时报错'module' object has no attribute 'lru_cache'

    使用pip方法安装Django时报错'module' object has no attribute 'lru_cache' 解决办法如下 命令行输入命令sudo pip install Django ...

随机推荐

  1. dns-prefetch对网站速度能提升有多少?详解dns-prefetch。

    DNS解析场景 有很多大型的网站,都会用N 个CDN 域名来做图片.静态文件等资源访问.比如新浪,我们经常会看到有下列域. img1.sina.com.cn . img2.sina.com.cn .i ...

  2. Python学习笔记(三)Python基本数字类型及其简单操作(1)

    一.数字类型 表示数字或数值的数据类型称为数字类型,Python语言提供3种数字类型:整数.浮点数和复数,分别对应数学中的整数.实数和复数,下面就一起来了解一下他们吧! 1.整数类型 整数类型与数学中 ...

  3. oracle 索引监控

           索引对于在大量数据里检索出少量数据库的查询操作来说是高效的,可是对于DML操作来说.却是负面的:①其对于insert 操作的反面影响最大.该表的索引越多,更新的索引越多,insert 操 ...

  4. RestController注解下返回到jsp视图页面(转)

    这个问题我也遇到过,下面的方法可以试试 蓝萝卜blu @RestController注解下返回到jsp视图页面 spring4.1中添加了@RestController注解很方便,集成了@Respon ...

  5. IO-01. 表格输出

    本题要求编写程序,按照规定格式输出表格. 输入格式: 本题目没有输入. 输出格式: 要求严格按照给出的格式输出下列表格: ------------------------------------Pro ...

  6. R语言Switch语句

    R语言Switch语句 switch语句允许一个变量值的列表来平等进行测试.每个值被称为一个条件(情况),变量被接通检查每个条件(情况). 语法 在R语言中创建switch语句的基本语法是: 以下规则 ...

  7. day39 10-Spring的AOP:基于AspectJ的切点定义

    切点是我们真正应用在哪些方法上,增强的那些方法上,就是add().update()和find().delete()是没用的.没用的话就是这三个方法.为什么要定义一个切点呢? 所以可以直接在切面中定义一 ...

  8. 2019-8-31-C#-循环的判断会进来几次

    title author date CreateTime categories C# 循环的判断会进来几次 lindexi 2019-08-31 16:55:58 +0800 2018-06-14 0 ...

  9. 提取网址的python练习

    import urllib, urllib2, cookielib from HTMLParser import HTMLParser import sys reload(sys) sys.setde ...

  10. 使用PHP类TCPDF生成PDF文档

    转自:http://www.blhere.com/1180.html 这两天遇到一个项目中,需要php自动处理生成pdf文档.在网上找了好几个类,最后决定使用TCPDF,使用的时候真是发现这个类真是强 ...