Python系列教程(三十):Functools模块

    之前在学习装饰器的时候,为了解决使用装饰器的副作用,我们使用了functools模块的update_wrapper和wraps方法。functools模块还有几个比较实用的方法,今天就一并介绍。

  一、Functools模块  

1、partial:偏函数

    作用:偏函数可以把函数的部分参数使用默认值固定下来,然后返回一个新的函数,相当于给一个函数的部分参数添加了一个隐藏的固定的默认值,当一个函数的参数非常复杂的时候,使用偏函数可以简化函数的调用

    格式partial(fun, *args, **kwargs) -> NewFun

  方法1:使用关键字固定参数 

    如果使用关键字参数固定部分参数,再调用新函数的时候,可以通过关键字传参覆盖固定的默认值

import functools

def add(x, y) -> int:
    return x + y

#使用关键字固定参数        
>>>newadd = functools.partial(add, y=5)

>>>newadd(7)
12

#关键字传参可以覆盖固定参数
>>>print(newadd(7, y=6))
13

#通过位置参数传参,不会覆盖固定参数
>>>newadd(7,9)
TypeError: add() got multiple values for argument 'y'

  方法2:使用位置参数固定参数 

    如果使用位置参数固定参数,再调用新函数的时候,使用位置参数传参的话,是不会覆盖固定的默认值

def add(x, y, *args) -> int:
    print(args)
    return x + y
newadd = functools.partial(add, 1,3,6,5)

#在固定默认值的时候,x = 1,y =3,后面传的参数不会覆盖
>>>newadd(7)
(6, 5, 7)
4

#相当于newadd(1, 3, 6, 5, y=20, x=26)
>>>newadd(y=20, x=26)
TypeError: add() got multiple values for argument 'y'

  parital函数的本质:

    ① 为什么通过关键字固定参数会覆盖,因为调用了update更新关键字的字典

    ② 为什么通过位置参数固定的不会被覆盖,因为使用了‘+’拼接了两个元组,最后通过参数解析的时候,固定的位置参数和新传入的位置参数都会用到,而且固定的位置参数的优先级是高于传入的位置参数的优先级

#partial的核心代码
def partial(func, *args, **keywords): 
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)

2、lru_cache:缓存

    作用:可以给函数增加缓存功能,当一个函数执行后,会将返回值和对应的参数列表缓存下来,当下次有同样的参数列表调用时,可以直接将结果返回出去,不需要再执行。所以在某些应用场景,如果一个函数需要被调用多次,而且每一次的执行时间都很长的话,可以考虑使用cache功能。

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

    lru_cache使用说明

        lur_cache是一个缓存装饰器,只要在需要这个功能的函数装饰一下即可。

        maxsize:缓存大小,默认128,使用lru算法清理缓存:Least-recently-used,是最近最少使用的含义。如果设置为None,则表示不限制缓存大小。
        typed:如果typed设置为True,则不同类型的函数参数将单独缓存。例如,f(3)和f(3.0)将被视为具有不同结果的不同调用。

    lru_cache缺点

        ① 不支持缓存过期,缓存的结果长期有效
        ② 不支持清除缓存操作
        ③ 不支持分布式

import functools
import time

#使用cache装饰函数
@functools.lru_cache()
def add(x, y, z=3):
    time.sleep(z)
    return x + y

#首次调用,sleep了3秒        
>>>add(4, 5)    
9  

#再次调用,直接返回结果
>>>add(4.0, 5)
9

   

Jimmy's Blog ,版权所有丨如未注明,均为原创丨本网站采用BY-NC-SA协议进行授权,转载请注明转自:https://www.xjimmy.com/python-30-functools.html

Leave a Comment