• functools模块(partial,lru_cache装饰器)


    partial方法

    偏函数,把函数部分的参数固定下来,相当于为部分的参数添加了一个固定的默认值,形成一个新的函数并返回。从partial生成的新函数,是对原函数的封装。

    import functools
    
    def add(x, y) -> int:
        return x + y
    
    newadd = functools.partial(add, y=5)
    
    print(newadd(7))
    print(newadd(7, y=6))
    print(newadd(y=10, x=6))
    
    import inspect
    print(inspect.signature(newadd))
    
    结果为:
    
    12
    13
    16
    (x, *, y=5) -> int
    import functools
    
    def add(x, y, *args) -> int:
        print(args)
        return x + y
    
    newadd = functools.partial(add, 1,3,6,5)
    
    print(newadd(7))
    print(newadd(7, 10))
    print(newadd(9, 10, y=20, x=26)) #
    print(newadd())
    
    import inspect
    print(inspect.signature(newadd))
    
    
    结果为:
    
    (6, 5, 7)
    4
    (6, 5, 7, 10)
    4
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-148-942fbd3d1b1e> in <module>
          9 print(newadd(7))
         10 print(newadd(7, 10))
    ---> 11 print(newadd(9, 10, y=20, x=26)) #
         12 print(newadd())
         13 
    
    TypeError: add() got multiple values for argument 'y'

    partial函数本质

    def partial(func, *args, **keywords):
        def newfunc(*fargs, **fkeywords): # 包装函数
            newkeywords = keywords.copy()
            newkeywords.update(fkeywords)
            return func(*(args + fargs), **newkeywords)
        newfunc.func = func # 保留原函数
        newfunc.args = args # 保留原函数的位置参数
        newfunc.keywords = keywords # 保留原函数的关键字参数参数
        return newfunc
    
    def add(x,y):
        return x+y
    
    foo = partial(add,4)
    foo(5)
    
    结果为:
    9

    @functools.lru_cache(maxsize=128, typed=False)

    Least-recently-used装饰器。lru——最近最少使用。cache缓存。缓冲和缓存是两回事。

    如果maxsize设置为None,则禁用LRU功能,并且缓存可以无限制增长。当maxsize是二的幂时,LRU功能执行得最好。

    如果typed设置为True,则不同类型的函数参数将单独缓存。例如,f(3)和f(3.0)将被视为具有不同结果的不同调用。

    import functools
    import time
    @functools.lru_cache()
    def add(x, y, z=3):
        time.sleep(z)
        return x + y
    
    print(add(4, 5))
    print(add(4.0, 5))
    print(add(4, 6))
    print(add(4, 6, 3))
    print(add(6, 4))
    print(add(4, y=6))
    print(add(x=4, y=6))
    print(add(y=6, x=4))
    
    
    结果为:
    9
    9
    10
    10
    10
    10
    10
    10

    计算过的值可以很快的得到结果,缓存的机制是什么?

    lru_cache装饰器

    通过一个字典缓存被装饰函数的调用和返回值,key是什么?分析代码看看。

    functools._make_key((4,6),{'z':3},False)
    
    结果为:
    [4, 6, <object at 0x844718>, 'z', 3]
    
    functools._make_key((4,6,3),{},False)
    结果为:
    [4, 6, 3]
    
    functools._make_key(tuple(),{'z':3,'x':4,'y':6},False)
    结果为:
    [<object at 0x844718>, 'z', 3, 'x', 4, 'y', 6]
    
    functools._make_key(tuple(),{'z':3,'x':4,'y':6}, True)
    结果为:
    [<object at 0x844718>, 'z', 3, 'x', 4, 'y', 6, int, int, int]

    可以用lru_cache装饰器实现对斐波那契数列递归方法的改造

    import functools
    
    @functools.lru_cache() # maxsize=None
    def fib(n):
        if n < 3:
            return n
        return fib(n-1) + fib(n-2)
    
    print([fib(x) for x in range(35)])
    
    
    结果为:
    
    [0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465]

    lru_cache装饰器应用

    使用前提:同样的函数参数一定得到同样的结果,函数执行时间很长,且要多次执行,本质是函数调用的参数=>返回值

    缺点:不支持缓存过期,key无法过期、失效,不支持清除操作,不支持分布式,是一个单机的缓存。

    适用场景,单机上需要空间换时间的地方,可以用缓存来将计算变成快速的查询。

     装饰器应用练习

    一、实现一个cache装饰器,实现可过期被清除的功能

    简化设计,函数的形参定义不包含可变位置参数、可变关键词参数和keyword-only参数

    可以不考虑缓存满了之后的换出问题

    二、写一个命令分发器

    程序员可以方便的注册函数到某一个命令,用户输入命令时,路由到注册的函数

    如果此命令没有对应的注册函数,执行默认函数

    用户输入用input(">>")



     
     
  • 相关阅读:
    随机发牌 代码
    网络传输 buf 封装 示例代码
    简易数据库实现 UNIX环境高级编程(APUE)第二十章 A Database Library
    状态机学习(六)解析JSON2
    又一篇四则运算代码
    c++ stl源码剖析学习笔记(三)容器 vector
    c++ stl源码剖析学习笔记(二)iterator
    Linux系统编程(16)——正则表达式入门
    Linux系统编程(15)——shell脚本语法
    Linux系统编程(14)——shell常用命令
  • 原文地址:https://www.cnblogs.com/xpc51/p/11710768.html
Copyright © 2020-2023  润新知