现在你已经看到了如何自己实现一个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。

用functools.lru_cache实现Python的Memoization的更多相关文章

  1. python functools.lru_cache做备忘功能

    import time import functools def clock(func): @functools.wraps(func)#还原被装饰函数的__name__和__doc__属性 def ...

  2. @functools.lru_cache()

    django.views.debug.get_default_exception_reporter_filter @functools.lru_cache()def get_default_excep ...

  3. functools.lru_cache装饰器

    functools.lru_cache装饰器 functools.lru_cache是非常实用的装饰器,他实现了备忘功能它把耗时的函数的结果保存起来,避免传入相同的参数时重复计算.LRU是Least ...

  4. 通过源码学习@functools.lru_cache

    一.前言 通常在一些代码中包含了重复运算,而这些重复运算会大大增加代码运行所耗费的时间,比如使用递归实现斐波那契数列. 举个例子,当求 fibonacci(5) 时,需要求得 fibonacci(3) ...

  5. Python 缓存机制与 functools.lru_cache(zz)

    refer to: http://kuanghy.github.io/2016/04/20/python-cache

  6. Nginx插件之openresty反向代理和日志滚动配置案例

    Nginx插件之openresty反向代理和日志滚动配置案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.openresty介绍 1>.Nginx介绍 Nginx是一款 ...

  7. Python标准库: functools (cmp_to_key, lru_cache, total_ordering, partial, partialmethod, reduce, singledispatch, update_wrapper, wraps)

    functools模块处理的对象都是其他的函数,任何可调用对象都可以被视为用于此模块的函数. 1. functools.cmp_to_key(func) 因为Python3不支持比较函数,cmp_to ...

  8. 标准库中最值得关注的两个 装饰器是 lru_cache 和全新的 singledispatch(Python 3.4 新增)

    clock 装饰器 def clock(func): @functools.wraps(func) def clocked(*args, **kwargs): t0 = time.perf_count ...

  9. Python进阶3---python类型注解、functools

    函数定义的弊端 函数注解Function Annotations 业务应用 inspect模块 #示例 import inspect def add(x,y:int,*args,**kwargs) - ...

随机推荐

  1. 新手必备 | 史上最全的PyTorch学习资源汇总

    目录: PyTorch学习教程.手册 PyTorch视频教程 PyTorch项目资源      - NLP&PyTorch实战      - CV&PyTorch实战 PyTorch论 ...

  2. CSS3动画的使用以及优化

    CSS3 动画 目录 1. 定义动画2. animation 属性3. animation 属性的兼容4. animation与transition 属性的取别5. animate.css 动画库6. ...

  3. [codevs2370]小机房的树<LCA>

    题目链接:http://codevs.cn/problem/2370/ 这题我还是做了比较久了,因为有人告诉我这是用tarjan离线做 好吧算我是蒟蒻,真心不懂tarjan怎么做,最后还是用倍增做的 ...

  4. 牛客寒假基础集训营 | Day1 J题—u's的影响力(水题)

    Day1 J题-u's的影响力 有一天,kotori发现了一个和lovelive相似的游戏:bangdream.令她惊讶的是,这个游戏和lovelive居然是同一个公司出的! kotori经过一段时间 ...

  5. HTTP Session例子

    HTTP协议是“一次性单向”协议.服务端不能主动连接客户端,只能被动等待并答复客户端请求.客户端连接服务端,发出一个HTTP Request,服务端处理请求,并且返回一个HTTP Response给客 ...

  6. 这些基本的 HTML5 标签你不能不知道

    HTML5元素 HTML5是HTML最新的修订版本,2014年10月由万维网联盟(W3C)完成标准制定. HTML5是用来写网页的一门标记语言. 使用的时候需要在首行声明HTML,如:<!DOC ...

  7. spring使用jdbc

    对于其中的一些内容 @Repository(value="userDao") 该注解是告诉Spring,让Spring创建一个名字叫“userDao”的UserDaoImpl实例. ...

  8. dockerfile_php_apache

    apache-alpine.docker php-apache.docker php-alpine php-apache-alpine.docker FROM httpd:2.4.39-alpine

  9. 【摸鱼向】UE4的AI模块探索手记(1)

    前言 之前实现了自主创作的角色导入进UE4并成功控制其进行一系列动作,但目前的样子距离基本的游戏架构还差了一个很大的模块:NPC,而这部分是由电脑来进行自动控制,所以,我有一句话不知当讲不当讲(对,我 ...

  10. 我对KMP算法的理解

    KMP算法的核心在于失配回溯表——pnext,相比于通过逐个比较来匹配字符串的朴素算法,KMP通过对模式串的分析,可以做到比较指针在主串上不回溯,一直向前. 1. KMP如何实现不回溯? 对于主串 t ...