天天看点

潇洒郎:Python funtools 库学习

functools 提供了 11个函数: 

  • cached_property()
  • cmp_to_key()
  • lru_cache()
  • partial()
  • partialmethod()
  • reduce()
  • singledispatch()
  • singledispatchmethod()
  • total_ordering()
  • update_wrapper()
  • wraps()

@cached_property - 缓存实例方法

它的目的是将类的一个方法转换为一个属性,该属性的值只计算一次,然后被缓存为实例生命周期中的一个普通属性。其行为与内置的@property 装饰器[2]非常相似,只是增加了缓存过程。让我们来看一下来自Python文档中的例子:

1.将方法转换为缓存属性,只计算一次,然后缓存'
@ft.cached_property      
class Dateset:
    def __init__(self, sequence_of_numbers):
        self._data = sequence_of_numbers

    '将方法转换为缓存属性,只计算一次,然后缓存'
    @ft.cached_property
    def stdev(self): # 计算标准差
        return statistics.stdev(self._data)

    @ft.cached_property
    def variance(self): # 计算方差
        return statistics.variance(self._data)
           
2.一个转换函数
cmp_to_key()
理解比较函数和键函数之间的区别
比较函数:第一个数相比第一个数; 0:等于, 1:大于,-1:小于
键函数:一个可调用的对象,接受一个参数并返回另一个用作排序键的值
函数通常会被提供给像sort()、min()和max()之类的内置函数。
cmp_to_key()会将一个比较函数转换为一个键函数
3. @lru_cache() - 通过缓存增加代码性能,是一个装饰器,
它用一个记忆化的可调用对象来包装一个函数,这个可调用对象可以保存最近的maxsize次调用(默认值:128)。      
@ft.lru_cache(maxsize=32) # 缓存大小设置为32
def get_pep(number: int)->str:   # (number:int)->str: 等价于(number)
    resource= f"http://www.python.org/dev/peps/pep-{number:04d}/"  # number:04d 取4位格式
    print(resource)
    try:
        with request.urlopen(resource) as s:
            return s.read()
    except error.HTTPError:
        return "Not Found"

list_of_peps = [8,290,308,320,8,218,320,279,289,320,9991]
# 总共11条,会调用8次,另外3次调用缓存值
for i in list_of_peps:
    pep= get_pep(i)  # i相同时不会重复执行,直接输出结果,8(2次),320(3次)
    print(i,len(pep))
print(get_pep.cache_info())
# 使用了3次缓存值,而不是再调用
#CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)
           
http://www.python.org/dev/peps/pep-0008/
8 103972
http://www.python.org/dev/peps/pep-0290/
290 60728
http://www.python.org/dev/peps/pep-0308/
308 57934
http://www.python.org/dev/peps/pep-0320/
320 50512
8 103972
http://www.python.org/dev/peps/pep-0218/
218 47756
320 50512
http://www.python.org/dev/peps/pep-0279/
279 49514
http://www.python.org/dev/peps/pep-0289/
289 51843
320 50512
http://www.python.org/dev/peps/pep-9991/
9991 9
CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)
           
4. @total_ordering - 通过使用装饰器来减少代码行数
      
@ft.total_ordering
class Pythonista:
    firstname:str
    lastname:str

    def __init__(self, firstname:str,lastname:str)->None:
        self.firstname = firstname
        self.lastname = lastname

    def __eq__(self, other:object)->bool:
        if not isinstance(other, Pythonista):
            return NotImplemented
        return ((self.lastname.lower(),self.firstname.lower())==(other.lastname.lower(),other.firstname.lower()))
    def __lt__(self, other:object)->bool:
        if not isinstance(other, Pythonista):
            return NotImplemented
        return ((self.lastname.lower(),self.firstname.lower())<(other.lastname.lower(),other.firstname.lower()))

guido= Pythonista('Guido','van Rossum')
brett= Pythonista("Brett","Cannon")

print(guido>brett) #True
           

 5.reduce 基于多个值计算单个值

# ft.reduce 基于多个值计算单个值
import operator as opt
iterable=[i for i in range(1,6)]
# opt.add,opt.mul 只能计算两个数的和和乘积

result= ft.reduce(opt.add, iterable)
print(result) # 计算之和
result= ft.reduce(opt.mul, iterable)
print(result) # 计算乘积
           

[email protected] - 函数重载 

# @singledispatch - 函数重载
#@singledispatch装饰器会将一个函数转换为一个
# 单分派泛函数。在@singledispatch的情况下,
# 分派发生在第一个参数的类型上。
# 加载函数上给函数提供注册功能
@ft.singledispatch
def mul(a,b):
    return a*b
@mul.register
def _(a:str, b:str):
    return a+b

print(mul(1,2))
print(mul('1','2'))
           

 [email protected] - 方法重载

# @singledispatchmethod - 方法重载

class Negator:
    @ft.singledispatchmethod
    def neg(self,arg):
        raise NotImplementedError("Cannot negate a")
    @neg.register
    def _(self,arg:int):
        return -arg
    @neg.register
    def _(self,arg:bool):
        return not arg
print(Negator().neg(5))
print(Negator().neg(False))
#print(Negator().neg("hello"))
           

8.wraps 打印func的备注信息

参考博客:https://mp.weixin.qq.com/s?src=11&timestamp=1631928439&ver=3321&signature=MuIgp-dOGZb4kxlLjUoi8kTaIEfcspwwaVVTrsJraIX2WmWp346x58pznYwp*9x2deiG6z1jLtRGKQQLq7N8JtTjJ*O0Xxr0jkCASApwqTIf*jk9VZ5JwzFMf3KrwQ4D&new=1