functools---高阶函数和可调用对象上的操作
模块应用于高阶函数,即参数或(和)返回值为其他函数的函数,此模块的功能适用于所有可调用对象。
1、方法和属性
1)cache(user_function):简单轻量级未绑定函数缓存。返回值与lru_cache(maxsize=None)相同,创建一个查找函数参数的字典的简单包装器。因为他不需要移出旧值,所以比带有大小限制的lru_cache(maxsize=None)更小更快。
@cache
def factorial(n):
return n * factorial(n-1) if n else 1
>>> factorial(10) # no previously cached result, makes 11 recursive calls
3628800
>>> factorial(5) # just looks up cached value result
120
>>> factorial(12) # makes two new recursive calls, the other 10 are cached
479001600
2)cache_property(func):将一个类方法转换为特征属性,一次性计算该特征属性的值,然后将其缓存为实例生命周期内的普通属性。类似于property()但增加了缓存功能,对于其他情况下实际不可变的高计算资源消耗的实例特征属性来说该函数非常有用。
class DataSet:
def __init__(self, sequence_of_numbers):
self._data = tuple(sequence_of_numbers)
@cached_property
def stdev(self):
return statistics.stdev(self._data)
cache_property()的设定与property()有所不同。常规的property会阻止属性写入,除非定义了setter,cache_property允许写入。
cached_property 装饰器仅在执行查找且不存在同名属性时才会运行。 当运行时, cached_property 会写入同名的属性。 后续的属性读取和写入操作会优先于 cached_property 方法,其行为就像普通的属性一样。
缓存的值可通过删除该属性来清空。 这允许 cached_property 方法再次运行。
注意,这个装饰器会影响 PEP 412 键共享字典的操作。 这意味着相应的字典实例可能占用比通常时更多的空间。
而且,这个装饰器要求每个实例上的 __dict__
是可变的映射。 这意味着它将不适用于某些类型,例如元类(因为类型实例上的 __dict__
属性是类命名空间的只读代理),以及那些指定了 __slots__
但未包括 __dict__
作为所定义的空位之一的类(因为这样的类根本没有提供 __dict__
属性)。
如果可变的映射不可用或者如果想要节省空间的键共享,可以通过在 cache() 之上堆叠一个 property() 来实现类似 cached_property() 的效果:
class DataSet:
def __init__(self, sequence_of_numbers):
self._data = sequence_of_numbers
@property
@cache
def stdev(self):
return statistics.stdev(self._data)
3)cmp_to_key(func):将比较函数转换为新式的key function,在类似与sorted(),min(),heapq.nlargest(),heapq.nsmallest(),itertools.groupby()等函数的key参数中使用。
比较函数意为一个可调用对象,该对象接受两个参数并比较他们,结果为小于则返回一个负数,相等则返回零,大于则返回一个正数,key function则是一个接受一个参数,并返回一个用以排序的值的可调用对象。
sorted(iterable, key=cmp_to_key(locale.strcoll)) # locale-aware sort order
4)lru_cache(maxsize=128,typed=False):为函数提供缓存的装饰器,缓存maxsize组传入参数,在下次以相同参数调用时直接返回上一次的结果,用以节约高开销或I/O函数的调用时间。
由于使用了字典存储缓存,所以该函数的固定参数和关键字参数必须是可哈希的。
不同模式的参数可能被视为不同从而产生多个缓存项,例如, f(a=1, b=2) 和 f(b=2, a=1) 因其参数顺序不同,可能会被缓存两次。
如果指定了 user_function,它必须是一个可调用对象。 这允许 lru_cache 装饰器被直接应用于一个用户自定义函数,让 maxsize 保持其默认值 128:
@lru_cache
def cou