天天看點

潇灑郎: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