zoukankan      html  css  js  c++  java
  • functools.lru_cache装饰器

    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装饰的函数接受的参数必须是不可变类型。

  • 相关阅读:
    Python 类中方法的内部变量,命名加'self.'变成 self.xxx 和不加直接 xxx 的区别
    用foreach遍历 datagridView 指定列所有的内容
    treeView1.SelectedNode.Level
    YES NO 上一个 下一个
    正则 单词全字匹配查找 reg 边界查找 精确匹配 只匹配字符 不含连续的字符
    抓取2个字符串中间的字符串
    sqlite 60000行 插入到数据库只用不到2秒
    将多行文本以单行的格式保存起来 读和写 ini
    将秒转换成时间格式
    richtextbox Ctrl+V只粘贴纯文本格式
  • 原文地址:https://www.cnblogs.com/liao-lin/p/10855288.html
Copyright © 2011-2022 走看看