英文原文出自:https://docs.python.org/2/library/functools.html
functools 是一系列高階函數的集合,這些函數可以接受其他函數作為參數或者傳回其他函數。一般說來,凡是可被調用的對象,都可以當成這個子產品的作用對象。
functools 子產品定義了下面的一系列函數:
functools.
cmp_to_key
(func)
functools.
cmp_to_key
cmp_to_key可以将老式風格的比較函數轉換成比較關鍵字函數。這個函數用在接收比較關鍵字函數作為參數的函數中(比如
sorted()
,
min()
,
max()
,
heapq.nlargest()
,
heapq.nsmallest()
,
itertools.groupby()
)。因為在Python3中不再支援老式風格的比較函數,這個函數也常被當成把python2的函數轉向python3的工具。
老式風格的比較函數是指,接收兩個參數進行比較,如果一個前者小于後者傳回一個負數,前者等于後者傳回0,前者大于後者傳回一個正數。比較關鍵字函數是指接收一個參數,傳回另外一個結果作為排序的關鍵字。
應用舉例:
from functools import cmp_to_key
def cmfunc(x,y):
if x>y:
return 1
elif x==y:
return 0
else:
return -1
seq=[2,1,4,5,3]
seq = sorted(seq,key=cmp_to_key(cmfunc))
for r in seq:
print r
輸出結果:
[email protected]:~/projects/PythonTs$ python cmp_to_keyTs.py
1
2
3
4
5
檢視更多排序的例子或者相關文檔請檢視 Sorting HOW TO .
functools.
total_ordering
(cls)
functools.
total_ordering
如果一個類中含有一個以上的用于比較的方法,這個類級别的修飾器會補充剩下的部分用于比較的方法,它簡化了在類中定義比較方法的繁重工作。
這個被修飾的類必須定義以下方法之一
__lt__()
,
__le__()
,
__gt__()
, or
__ge__()。另外,該類也必須實作
__eq__()
方法。
應用舉例:
@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()))
我們定義了Student類,隻聲明了__eq__和__lt__方法,當Student類被total_ordering修飾後,使用dir檢視Student的屬性,其他剩餘的比較函數都被自動定義:
>>> from total_orderingTs import Student
>>> dir(Student)
['__doc__', '__eq__', '__ge__', '__gt__', '__le__', '__lt__', '__module__']
>>>
functools.
reduce
(function, iterable[, initializer])
functools.
reduce
這個函數和reduce的功能一樣,它在functools子產品建立隻是為了使python3向前相容。
使用舉例:
from functools import reduce
def add(x,y):
return x+y
print reduce(add,[1,2,3,4,5])
reduce的功能是将list中的前兩個值作為參數傳給add函數,然後将add的結果和第三個值再次傳給add函數,以此類推,最終傳回一個結果:
[email protected]:~/projects/PythonTs$ python reduceTs.py
15
functools.
partial
(func[,*args][, **keywords])¶
functools.
partial
傳回一個新的partial(偏函數)對象,partial被調用時就像傳給它的func函數帶着參數args和keywords被調用一樣。如果func也附帶了自己的參數,那麼它的參數将被追加至args或者keywords中。大概等價于以下代碼:
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*(args + fargs), **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfun
partial()通過"當機"一個函數的部分參數而擷取一個偏函數對象,相當于簡化了原函數的簽名。比如說 partial()可以建立一個行為類似于base為2的int()函數:
>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18
應用舉例:
from functools import partial
def add(x,y,z):
return x+y+z
newadd=partial(add,y=1,z=2)
print newadd(3)
print newadd(55555)
我們用partial定義新的函數newadd,但是簡化了參數清單,隻傳入一個參數即可。
functools.
update_wrapper
(wrapper, wrapped[, assigned][, updated])
functools.
update_wrapper
使修飾函數更加符合被修飾函數。該函數中的後面可選參數是兩組元組,前者用來指定從被修飾函數中擷取哪些屬性給修飾函數,後者用來指定修飾函數中哪些屬性需要更新和被修飾函數一緻。這些參數的預設值都是子產品級别的限制,如WRAPPER_ASSIGNMENTS (在修飾函數中增加 __name__, __module__ 和 __doc__這些文檔屬性)和WRAPPER_UPDATES (更新修飾函數的__dict__屬性)
這個函數最主要的用處就是用在裝飾器中。如果裝飾器中的修飾函數沒有被更新,裝飾器的傳回函數的中繼資料将會映射修飾函數而非被修飾函數。
functools.
wraps
(wrapped[, assigned][, updated])
functools.
wraps
這個函數作為裝飾器,在定義修飾函數的時候可以很友善的激活update_wrapper。它等價于partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)。 應用舉例:
from functools import wraps
def decoratorWithoutWraps(f):
def wrapper_func(args):
"""wrapper doc"""
return f(args)
return wrapper_func
@decoratorWithoutWraps
def wrapped_func1(args):
"""wrapped1 doc"""
pass
def decoratorWithWraps(f):
@wraps(f)
def wrapper_func():
"""wrapper doc"""
return f()
return wrapper_func
@decoratorWithWraps
def wrapped_func2():
"""wrapped2 doc"""
pass
if __name__ =='__main__':
#without @wraps
print wrapped_func1.__name__
print wrapped_func1.__doc__
#with @wraps
print wrapped_func2.__name__
print wrapped_func2.__doc__
執行結果:
[email protected]:~/projects/PythonTs$ python wrapperTs.py
wrapper_func
wrapper doc
wrapped_func2
wrapped2 doc
對于修飾器函數前沒有使用@wraps的,列印出來的結果是定義的修飾器函數的__name__和__doc__,而對于修飾器前使用@wraps的,列印出來的是被修飾函數的 __name__和__doc__,顯然後者才是我們期望的。
Github位置:
https://github.com/HymanLiuTS/PythonTs
克隆本項目:
git clone [email protected]:HymanLiuTS/PythonTs.git
擷取本文源代碼:
git checkout PL02