用functools.lru_cache实现Python的Memoization

用functools.lru_cache实现Python的Memoization

现在你已经看到了如何自己实现一个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方法重置结果缓存:

本文来自企鹅号 - Python程序员媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Danny的专栏

【MyEclipse】——MyEclipse建立树形结构包

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

11210
来自专栏偏前端工程师的驿站

JS魔法堂:函数节流(throttle)与函数去抖(debounce)

一、前言                                     以下场景往往由于事件频繁被触发,因而频繁执行DOM操作、资源加载等重行为,导致...

25860
来自专栏安恒信息

近期APT攻击事件频发—安恒信息再次成功检测到APT攻击样本

>>>> 前言 乌克兰电力系统受到APT攻击事件,给国内外企业和用户都敲响了警钟,与此同时,安恒信息在国内也监控到了多次APT攻击。近期,安恒信息APT威胁分析...

37050
来自专栏技术之路

wpf 解决 编码解码器无法使用提供的流类型 The codec cannot use the type of stream provided

之前做的ListBox里列大图https://cloud.tencent.com/developer/article/1032668 图片转换的时候这段代码 ?...

21390
来自专栏码洞

深入理解 RPC 消息协议设计

本节我们开始讲解 RPC 的消息协议设计背后的基本原理,了解 RPC 的协议开发背后有哪些需要考虑的基本点。在通晓原理之后,我们就可以自己设计一套协议来开发属于...

14830
来自专栏CDA数据分析师

热度碾压 Java、C#、C++的 Python,为什么速度那么慢?

眼下 Python 异常火爆,不论是 DevOps、数据科学、Web 开发还是安全领域,都在用 Python——但是它在速度上却没有任何优势。

19610
来自专栏FreeBuf

代码安全审计:当file_exists遇上eval

起因 昨晚有人在一QQ群上问lcms(一款网站CMS系统)的一个漏洞是怎么形成的,说了半天。他截图不完整,于是叫他传代码,下载回来找到router.php代码片...

20590
来自专栏Ldpe2G的个人博客

ScalaMP ---- 模仿 OpenMp 的一个简单并行计算框架

11630
来自专栏玉树芝兰

如何让Jupyter Notebook支持多种编程语言?

不满意Jupyter Notebook只有Python 2环境,还打算让它支持Python 3与R?没问题,本文一步步帮助你实现这个愿望。

23810
来自专栏coding for love

JS常用设计模式解析02-策略模式

在于都本文之前,希望大家能够先阅读以下JS进阶系列03-JS面向对象的三大特征之多态这篇文章,了解JS的多态。在这篇文章,我们举了一个例子,就是选拔官员选拔合唱...

13530

扫码关注云+社区

领取腾讯云代金券