现在你已经看到了如何自己实现一个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. 一文上手Tensorflow2.0之tf.keras(三)

    系列文章目录: Tensorflow2.0 介绍 Tensorflow 常见基本概念 从1.x 到2.0 的变化 Tensorflow2.0 的架构 Tensorflow2.0 的安装(CPU和GPU ...

  2. Jmeter4.0接口测试之案例实战(七)

    在前面的知识体系中介绍了Jmeter的基本应用,下来通过具体的案例来看Jmeter在接口测试中的具体案例实战部分. HTTP是基于应用层的协议,底层的网络传输层它不需要去关心,同时它是一个无状态的协议 ...

  3. openssl与java(读取加密码的密钥)

    最近在研究java security方面的东西,java自带可以使用各种加密解密算法(rsa,dsa,des3,aes,md5...),但往往一些密钥是第三方给我们的,我们需要用java装载这些密钥然 ...

  4. 线程状态以及sleep yield wait join方法

    前言 在日常的开发过程中,我们通过会使用Thread.sleep模拟一个耗时的任务执行过程. 在深入理解这四个方法之前,首先对线程的状态进行理解阐述. 线程概念 线程是操作系统执行任务的基本单位,处理 ...

  5. opnet

    一.修改默认的文件管理 1.以管理员身份运行 opnet14.5 2. 3.初始默认是c盘下的op_madels 4.修改你默认的文件夹 二. 1.创建一个空场景 包含Manet模型 2. 出错 二. ...

  6. layuiadmin使用Ueditor 获取不了数据的解决方法

    表单根元素请使用form元素,layuiadmin 默认使用div作为表单根元素. <form class="layui-form"> <textarea nam ...

  7. NKOJ3765 k个最小和

    问题描述 有k个整数数组,各包含k个元素,从每个数组中选取一个元素加起来,可以得到k^k个和,求这些和中最小的k个值. 输入格式 第一行,一个整数k(k<=500)接下来k行,每行k个正整数(& ...

  8. Vertica的这些事(四)——-vertica加密数据

    通过创建 Secure Access Policies可以对vertica中的某一列数据进行加密: CREATE ACCESS POLICY ON [schema][tablename] FOR CO ...

  9. java对象转为json字符串

    1.使用fastjson开源json工具类库 2.java类未添加get()和set()方法,java对象初始化时,使用fastjson解析,得到的json字符串有时为空{} 3.Java对象转为js ...

  10. php静态变量的运用

    <?php $count = 5; function get_count() { static $count = 0; return $count++; } echo $count; echo ...