functools模塊提供了高階函數(shù)功能:函數(shù)可以作為或者返回其他函數(shù)琉历。通常硼端, 任何可調(diào)用對象可以被視為在本模塊的函數(shù)亚兄。
高階函數(shù)是指將函數(shù)作為傳參或返回值的函數(shù)低滩,即functools提供了一些工具顽冶,用來處理函數(shù)欺抗。包含的方法主要有cmp_to_key, partial, reduce, total_ordering, update_wrapper, wraps。
cmp_to_key
cmp_to_key的作用就是講cmp函數(shù)轉(zhuǎn)化為key函數(shù)强重。這里有兩個概念:
比較函數(shù)是任何一個可調(diào)用的函數(shù)绞呈,且包含兩個參數(shù),對參數(shù)進行比較间景,如果小于返回負數(shù)佃声,等于返回0,大于返回正數(shù)倘要。
關鍵函數(shù)是一種可調(diào)用函數(shù)圾亏。接受一個參數(shù),返回另一個表明其在期望序列中的位置的值封拧。
cmp_to_key應用在需要key函數(shù)作為參數(shù)的函數(shù)中志鹃,比如sorted, min, max等。我們用sorted函數(shù)舉例:
from functools import cmp_to_key
s1 = sorted(range(5)) # [0, 1, 2, 3, 4]
s2 = sorted(range(5), cmp=lambda x, y: x % 3 - y % 3)
s3 = sorted(range(5), key=lambda x: x % 3
s4 = sorted(range(5), key=cmp_to_key(lambda x, y: x % 3 - y % 3))
上面的例子中泽西,s1是默認排序曹铃;s2,s3捧杉,s4是等效的陕见,將0-4按照模3進行比較。s2指定了cmp函數(shù)味抖,s3指定了key函數(shù)淳玩,s4將s2的cmp函數(shù)轉(zhuǎn)換為key函數(shù)。
partial
partial是偏函數(shù)應用非竿,將函數(shù)的部分參數(shù)固定到新的函數(shù)中蜕着。一般實現(xiàn):
def add(x, y):
return x + y
def add2(y):
return add(2, y)
add2(3) # 5
上面的例子是將add函數(shù)的一個參數(shù)x=2固定到add2中。這個例子可以通過partial實現(xiàn):
def add(x, y):
return x + y
add2 = functools.partial(add, 2)
add2(3) # 5
reduce
就是python2 內(nèi)建函數(shù)reduce。在python3中reduce被移除內(nèi)建函數(shù)承匣,用functools.reduce可以向前兼容蓖乘。
total_ordering
total_ordering 同樣是 Python 2.7 中新增函數(shù),用于簡化比較函數(shù)的寫法韧骗。如果你已經(jīng)定義了 __eq__ 方法嘉抒,以及 __lt__、__le__袍暴、__gt__ 或者 __ge__ 其中之一些侍, 即可自動生成其它比較方法。官方示例:
@total_ordering
class Student:
def __eq__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) ==
(other.lastname.lower(), other.firstname.lower()))
def __lt__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) <
(other.lastname.lower(), other.firstname.lower()))
dir(Student) # ['__doc__', '__eq__', '__ge__', '__gt__', '__le__', '__lt__', '__module__']
warps
之前了解過裝飾器函數(shù)政模,裝飾器會有一個副作用岗宣,會把原函數(shù)的名字覆蓋掉。
def outer(fun):
def inner():
pass
return inner
@outer
def fun():
pass
f = fun
f.__name__ # inner
wraps用來解決這個問題淋样。
def outer(fun):
@wraps
def inner():
pass
return inner
@outer
def fun():
pass
f = fun
f.__name__ # fun
除了__name__外耗式,wraps還能修改的屬性可以通過functools.WRAPPER_ASSIGNMENTS查詢。
('__module__', '__name__', '__doc__')
update_wrapper
update_wrapper功能與wraps類似趁猴,后者可以看做前者的特化刊咳,可以理解為
wraps = partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)