Python中的functools模块
- update_wrapper(wrapper,wrapped,assigned=WRAPPER_ASSIGNMENTS,updated=WRAPPER_UPDATES)
- 功能类似上面代码中copy_property功能,帮助修改包装函数属性
- wrapper 包装还是、被更新者(需要更新者)
- wrapped 被包装函数、数据源
- assigned=WRAPPER_ASSIGNMENTS 其中WRAPPER_ASSIGNMENTS是一个元组
- WRAPPER_ASSIGNMENTS = (’__module__’, ‘__name__’, ‘__qualname__’, ‘__doc__’,
‘__annotations__’)
- updated=WRAPPER_UPDATES 其中 WRAPPER_UPDATES是一个元组
- WRAPPER_UPDATES = (’__dict__’,)
- 注意:在update_wrapper函数调用后,会新增加一个__wrapped__属性,记录了被包装函数wrapped
- 原码如下:
- 使用update_wrapper函数修改属性值如下:
- 运行结果如下:
- 其代码还可以修改为如下方式:
- 运行结果如下:
上面改造中使用了@functools.wraps(fn)
- wraps(wrapped,assigned = WRAPPER_ASSIGNMENTS,updated = WRAPPER_UPDATES)
- 类似logg功能
- wrapped被包装函数
- assigned=WRAPPER_ASSIGNMENTS 其中WRAPPER_ASSIGNMENTS是一个元组
- WRAPPER_ASSIGNMENTS = (’__module__’, ‘__name__’, ‘__qualname__’, ‘__doc__’,
‘__annotations__’)
- updated=WRAPPER_UPDATES 其中 WRAPPER_UPDATES是一个元组
- WRAPPER_UPDATES = (’__dict__’,)
- 注意:会新增加一个__wrapped__属性,记录了被包装函数wrapped
- wraps函数原码:
- reduce(function,iterable[,initializer]) #归纳计算。 通过指定函数将集合中的数据按照指定方式规整为一个数据。
- function 是个函数,用来定义规整方式
- iterables 可迭代对象
- initializer 设置规整时的初始值,默认值为None,会获取iterables中的第一个元素作为初始值。
- Python官方伪代码如下:
- partial(func, *args, **keywords)->fun #偏函数。
- 偏函数,把函数部分的参数固定下来,相当于为部分的参数添加了一个固定的默认值,形成一个新的函数并返回
- 从partial生成的新函数,是对函数的封装
- func #需要封装的函数
- *args #需要固定的位置参数
- **kwywords #需要固定的关键字参数
- 简单原码如下:
- 示例:
lru_cache缓存装饰器
- functools.lru_cache(maxsize=128,typed=False) #cache缓存。为函数添加缓存机制。通过一个字典缓存被装饰函数的调用和返回值。
- Least-recently-used装饰器。lru,最近最少使用。cache缓存
- maxsize:如果maxsize设置为None,则禁用LRU功能,并且缓存可以无限制增长。当maxsize是二的幂时,LRU功能执行得最好
- 如果typed设置为True,则不同类型的函数参数将单独缓存。例如f(3)和f(3.0)将被视为具有不同结果的不同调用
- 示例
- lru_cache装饰器
- 斐波拉契数列递归方法的改造
- lru_cache装饰器应用
- 使用前提
- 同样的函数参数一定得到同样的结果
- 函数执行时间很长,且要多次执行
- 本质是函数调用函数=》返回值
- 缺点
- 不支持缓存过期,key无法过期、失效
- 不支持清除操作
- 不支持分布式,是一个单机的缓存
- 适用场景,单机上需要空间换时间的地方,可以用缓存来将计算变成快速的查询
- 实现一个cache装饰器,实现可过期被清除的功能
- 简化设计,函数的形参定义不包含可变位置参数、可变关键字参数和keyword-only参数 可以不考虑缓存大小,也不用考虑缓存满了之后的换出问题