Python標準庫functools
functools模塊提供了高階函數功能:函數可以作爲或者返回其他函數。通常, 任何可調用對象可以被視爲在本模塊的函數。
高階函數是指將函數作爲傳參或返回值的函數,即functools提供了一些工具,用來處理函數。包含的方法主要有cmp_to_key, partial, reduce, total_ordering, update_wrapper, wraps。
cmp_to_key
cmp_to_key的作用就是講cmp函數轉化爲key函數。這裏有兩個概念:
比較函數是任何一個可調用的函數,且包含兩個參數,對參數進行比較,如果小於返回負數,等於返回0,大於返回正數。
關鍵函數是一種可調用函數。接受一個參數,返回另一個表明其在期望序列中的位置的值。
cmp_to_key應用在需要key函數作爲參數的函數中,比如sorted, min, max等。我們用sorted函數舉例:
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函數,s3指定了key函數,s4將s2的cmp函數轉換爲key函數。
partial
partial是偏函數應用,將函數的部分參數固定到新的函數中。一般實現:
def add(x, y):
return x + y
def add2(y):
return add(2, y)
add2(3) # 5
上面的例子是將add函數的一個參數x=2固定到add2中。這個例子可以通過partial實現:
def add(x, y):
return x + y
add2 = functools.partial(add, 2)
add2(3) # 5
reduce
就是python2 內建函數reduce。在python3中reduce被移除內建函數,用functools.reduce可以向前兼容。
total_ordering
total_ordering 同樣是 Python 2.7 中新增函數,用於簡化比較函數的寫法。如果你已經定義了 __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
之前瞭解過裝飾器函數,裝飾器會有一個副作用,會把原函數的名字覆蓋掉。
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)