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×tamp=1631928439&ver=3321&signature=MuIgp-dOGZb4kxlLjUoi8kTaIEfcspwwaVVTrsJraIX2WmWp346x58pznYwp*9x2deiG6z1jLtRGKQQLq7N8JtTjJ*O0Xxr0jkCASApwqTIf*jk9VZ5JwzFMf3KrwQ4D&new=1