functools.lru_cache装饰器

functools.lru_cache是非常实用的装饰器,他实现了备忘功能它把耗时的函数的结果保存起来,避免传入相同的参数时重复计算。LRU是Least Recently Used的缩写,表明缓存不会无限制增长,一段时间不用的缓存条目会被扔掉。

使用递归来生成斐波那契的第n个数

# clock 装饰器
import time
import functools def clock(func):
@functools.wraps(func)
def clocked(*args, **kwargs):
t0 = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - t0
name = func.__name__
arg_lst = []
if args:
arg_lst.append(', '.join(repr(arg) for arg in args))
if kwargs:
pairs = ['%s=%r' % (k, w) for k, w in sorted(kwargs.items())]
arg_lst.append(', '.join(pairs))
arg_str = ', '.join(arg_lst)
print('[%0.8fs] %s(%s) -> %r ' % (elapsed, name, arg_str, result))
return result
return clocked # 利用递归方式生成斐波那契
@clock
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 2) + fibonacci(n - 1) if __name__ == '__main__':
print(fibonacci(6)) '''
[0.00000000s] fibonacci(0) -> 0
[0.00000000s] fibonacci(1) -> 1
[0.00081015s] fibonacci(2) -> 1
[0.00000000s] fibonacci(1) -> 1
[0.00000000s] fibonacci(0) -> 0
[0.00000000s] fibonacci(1) -> 1
[0.00000000s] fibonacci(2) -> 1
[0.00000000s] fibonacci(3) -> 2
[0.00081015s] fibonacci(4) -> 3
[0.00000000s] fibonacci(1) -> 1
[0.00000000s] fibonacci(0) -> 0
[0.00000000s] fibonacci(1) -> 1
[0.00000000s] fibonacci(2) -> 1
[0.00081134s] fibonacci(3) -> 2
[0.00000000s] fibonacci(0) -> 0
[0.00000000s] fibonacci(1) -> 1
[0.00000000s] fibonacci(2) -> 1
[0.00000000s] fibonacci(1) -> 1
[0.00000000s] fibonacci(0) -> 0
[0.00000000s] fibonacci(1) -> 1
[0.00000000s] fibonacci(2) -> 1
[0.00000000s] fibonacci(3) -> 2
[0.00000000s] fibonacci(4) -> 3
[0.00081134s] fibonacci(5) -> 5
[0.00162148s] fibonacci(6) -> 8
8
'''

可以看出使用递归会进行很多重复的计算,数据量增多时调用和计算更多。

使用functools.lru_cache优化

# clock 装饰器
import time
import functools def clock(func):
@functools.wraps(func)
def clocked(*args, **kwargs):
t0 = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - t0
name = func.__name__
arg_lst = []
if args:
arg_lst.append(', '.join(repr(arg) for arg in args))
if kwargs:
pairs = ['%s=%r' % (k, w) for k, w in sorted(kwargs.items())]
arg_lst.append(', '.join(pairs))
arg_str = ', '.join(arg_lst)
print('[%0.8fs] %s(%s) -> %r ' % (elapsed, name, arg_str, result))
return result
return clocked # 利用递归方式生成斐波那契
@functools.lru_cache()
@clock
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 2) + fibonacci(n - 1) if __name__ == '__main__':
print(fibonacci(6)) '''
[0.00000000s] fibonacci(0) -> 0
[0.00000000s] fibonacci(1) -> 1
[0.00000000s] fibonacci(2) -> 1
[0.00000000s] fibonacci(3) -> 2
[0.00000000s] fibonacci(4) -> 3
[0.00000000s] fibonacci(5) -> 5
[0.00000000s] fibonacci(6) -> 8
8
'''

可以看到使用lru_cache性能会显著改善。需要注意的是被lru_cache装饰的函数接受的参数必须是不可变类型。

functools.lru_cache装饰器的更多相关文章

  1. python中functools.wraps装饰器的作用

    functools.wraps装饰器用于显示被包裹的函数的名称 import functools def node(func): #@functools.wraps(func) def wrapped ...

  2. python functools.wraps装饰器模块

    # -*-coding=utf-8 -*-#实现一个函数执行后计算执行时间的功能 __author__ = 'piay' import time, functools def foo(): ''' 定 ...

  3. Python 标准库中的装饰器

    题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...

  4. 用functools.lru_cache实现Python的Memoization

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

  5. python 函数结果缓存一段时间的装饰器

    把函数结果缓存一段时间,比如读取一个mongodb,mongodb中的内容又在发生变化,如果从部署后,自始至终只去读一次那就感触不到变化了,如果每次调用一个函数就去读取那太频繁了耽误响应时间也加大了c ...

  6. Python基础:13装饰器

    装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的应用有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同 ...

  7. Fluent_Python_Part3函数即对象,07-closure-decoration,闭包与装饰器

    第7章 函数装饰器和闭包 装饰器用于在源码中"标记"函数,动态地增强函数的行为. 了解装饰器前提是理解闭包. 闭包除了在装饰器中有用以外,还是回调式编程和函数式编程风格的基础. 1 ...

  8. python 装饰器(三):装饰器实例(一)

    示例 7-15 定义了一个装饰器,它会在每次调用被装饰的函数时计时,然后把经过的时间.传入的参数和调用的结果打印出来.示例 7-15 一个简单的装饰器,输出函数的运行时间 import time de ...

  9. python函数与方法装饰器

    之前用python简单写了一下斐波那契数列的递归实现(如下),发现运行速度很慢. def fib_direct(n): assert n > 0, 'invalid n' if n < 3 ...

随机推荐

  1. double,float,BigDecimal类型数值的操作

    float四舍五入保留两位小数 /** * float四舍五入保留两位小数 * */ public static float formatDecimal(float n) { return (Math ...

  2. es6 是否包含字符串判断

    字符串查找类 接下来介绍一些可以通过 ES5 PolyFill的方法,但是现在 ES6 原生实现了 Method Param Return Description includes() 需要验证是否被 ...

  3. django的邮件email功能

    注意 测试的时候python manage.py test -p "test_tasks.py" -v 3,默认使用的EMAIL_BACKEND配置为:'django.core.m ...

  4. python中dict对象和字符串string对象互相转换

    使用json包 import json dict1 = {"A":"a","B":"b"} # 转换为字符串 json. ...

  5. Unity3d NavMeshAgent 寻路问题(1)

    navMeshAgent调用setDestination 后,会有一个计算路径的时间,计算过程中pathPending为true. 在这个过程中remainingDistance一直为0.

  6. 【编程开发】 C与C++中的关于函数指针的强制类型转换与指针函数的关系

    [编程开发] C与C++中的关于函数指针的强制类型转换与指针函数的关系 标签: [编程开发] [VS开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 以 ...

  7. 最新 美图java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.美图等10家互联网公司的校招Offer,因为某些自身原因最终选择了美图.6.7月主要是做系统复习.项目复盘.LeetCode ...

  8. gx_dlms 的杂乱记录

    DLMS_ERROR_CODE_FALSE W3Jehpnc543MuwUz6ZWDshy5kwbbE9Cw CGXDLMSClient::GetData(CGXByteBuffer& rep ...

  9. PYTHON 100days学习笔记008-3:输入和输出

    目录 Day008-03:Python3 输入和输出 1.输出格式美化 1.1 str.format()用法 1.2 旧式字符串格式化 2.读取键盘输入 3.读和写文件 4.文件对象的方法 4.1 f ...

  10. 快速Get-JAVA-IO流

    第四阶段 IO IO流 前言: 前面的学习我们只能够在已有的一定封闭范围内进行一些操作,但是这显然是无趣的,也是不支持我们实现一些复杂的需求,所以Java提供IO流这样一种概念,方便我们对数据进行操作 ...