力扣上看到一道题:

假设你正在爬楼梯。需要 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. 阿里云SaaS生态战略发布:成就亿级营收独角兽

    导语:本文中,阿里云智能资深技术专家黄省江从“势”“道”“术”三个方面分享了自己对于SaaS生态的理解,并介绍了SaaS加速器发布以来在产品.技术和商业侧最新的一些进展. 在321北京峰会上,阿里云公 ...

  2. webpack学习之——Entry Points(入口起点)

    1.Entry property(entry属性) 1.1 Single Entry (Shorthand) Syntax(单个入口语法) 用法:entry: string | Array<st ...

  3. Hdu 2389 二分匹配

    题目链接 Rain on your Parade Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 655350/165535 K (Ja ...

  4. js获取时间差值

    function GetTime(firstDate, secondDate) { // 1.对事件进行处理 var firsttime = Date.parse(firstDate + " ...

  5. Filter详解(转)

    以前以为Filter只是一个特殊点的Servlet,用进只需在web.xml中配置一下拦截路径就可以了,可经过这两天的深入学习,才知道以前对Filter类的了解和使用都太过浅薄了. 在网上看了很多篇相 ...

  6. Python数据分析与展示[第二周]

    matplotlib 有各种可视化的类构成 一般调用 matplotlib.pypolt 这个命令字库 相当于快捷方式 plt.plot(a) 只有一个一维列表 x轴充当列表索引 plt.ylabel ...

  7. OSGi教程:Framework Namespaces Specification

    此教程基于OSGi Core Release 7 OSGi命名空间规范 详细的教程上面的英文教程里面有详细说明. 我就记录一下自己看完之后的简单理解: OSGi的Namespace规范就是规定了你Ma ...

  8. 在Eclipse打开文件目录

    1.在Eclipse中使用外部命令 2.配置外部命令 3.设置使用的命令和参数 4.设置使用notepad++打开文件

  9. iOS9新系统下App Store应用上传新指南

    http://www.cocoachina.com/appstore/20151010/13691.html 最近频繁收到小伙伴们的反馈,说经过前期学习已对ASO规则略有了解,但APP的提交审核是由技 ...

  10. HTML 5适合小公司,适合在大平台上做内容

    Web App,现在有时候也称为轻应用,不仅是通过浏览器就能打开的应用.现在随着 HTML 5 在手机端的优越性,已经慢慢称为了 Web App 的主流.Web App 除了出现在 PC 的浏览器中, ...