該模塊為高階函數提供支持——作用於或返回函數的函數被稱為高階函數。在該模塊看來,一切可調用的對象均可視為本模塊中所說的“函數”。
目錄
2. functools.total_ordering(cls)
3. functools.reduce(function, iterable[, initializer])
*4. functools.partial(func[,*args][, **keywords])
5. functools.update_wrapper(wrapper, wrapped[, assigned][, updated])
*6. functools.wraps(wrapped[, assigned][, updated])
該模塊中定義了如下方法:
functools.cmp_to_key(func)
將老式的比較函數(comparison function)轉化為關鍵字函數(key function)。與接受key function的工具一同使用(如 sorted(), min(), max(), heapq.nlargest(), itertools.groupby())。該函數主要用來將程序轉成 Python 3 格式的,因為 Python 3 中不支持比較函數。
比較函數是可調用的,接受兩個參數,比較這兩個參數並根據他們的大小關系返回負值、零或正值中的某一個。關鍵字函數也是可調用的,接受一個參數,同時返回一個可以用作排序關鍵字的值。
例如:
sorted(iterable, key=cmp_to_key(locale.strcoll))
functools.total_ordering(cls)
這是一個類裝飾器,給定一個類,這個類定義了一個或多個比較排序方法,這個類裝飾器將會補充其余的比較方法,減少了自己定義所有比較方法時的工作量。
被修飾的類必須至少定義 __lt__(), __le__(), __gt__() 或 __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()))
functools.reduce(function, iterable[, initializer])
和 reduce() 方法的作用相同,這里提供了向 Python 3 過渡的前向支持。
functools.partial(func[,*args][, **keywords])
函數裝飾器,返回一個新的 partial 對象,關於 partial 對象的介紹見下文。調用 partial 對象就和調用被修飾的函數 func 相同,只不過調用 partial 對象時傳入的參數個數通常少於調用 func 時傳入的參數個數。 當一個函數 func 可以接收很多參數,而某一次使用只需要更改其中的一部分參數,其他的某些參數都保持不變時, partial 對象就可以將這些不變的對象凍結起來,這樣調用 partial 對象時傳入未凍結的參數, partial 對象調用 func 時連同已經被凍結的參數一同傳給 func 函數,從而簡化了調用過程。
如果調用 partial 對象時提供了更多的參數,那么他們會被添加到 args 的后面,如果提供了更多的關鍵字參數,那么它們將擴展或覆寫已經凍結的關鍵字參數
partial 對象的作用大抵如下:
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 newfunc
使用 partial 對象創建一個 base 參數始終為 2 的 int()
from functools import partial basetwo = partial(int, base=2) basetwo.__doc__ = 'Convert base 2 string to an int.' basetwo('10010')
這個新的 partial 對象 basetwo 能夠將二進制的參數轉化為十進制的整型結果,在調用這個 partial 對象時只需要傳入二進制的目標參數即可。
functools.update_wrapper(wrapper, wrapped[, assigned][, updated])
更新一個包裹(wrapper)函數,使其看起來更像被包裹(wrapped)的函數。
可選的參數指定了被包裹函數的哪些屬性直接賦值給包裹函數的對應屬性,同時包裹函數的哪些屬性要更新而不是直接接受被包裹函數的對應屬性。參數 assigned 的默認值對應於模塊級常量 WRAPPER_ASSIGNMENTS (默認地將被包裹函數的 __name__, __module__ 和 __doc__ 屬性賦給包裹函數), 參數 updatedd 的默認值對應於模塊級常量 WRAPPER_UPDATES (默認更新 wrapper 函數的 __dict__ 屬性)。
這個函數的主要用途是在一個裝飾器中,原函數會被裝飾(包裹),裝飾器函數會返回一個 wrapper 函數,如果裝飾器返回的這個 wrapper 函數沒有被更新,那么它的一些元數據更多的是反映 wrapper 函數定義時的特征,無法反映 wrapped 函數的特性。
functools.wraps(wrapped[, assigned][, updated])
這個函數可以用作一個裝飾器,簡化調用上一個函數 update_wrapper 的過程。調用這個函數等價於調用 partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated) 。
例如:
>>> from functools import wraps >>> def my_decorator(f): ... @wraps(f) ... def wrapper(*args, **kwds): ... print 'Calling decorated function' ... return f(*args, **kwds) ... return wrapper ... >>> @my_decorator ... def example(): ... """Docstring""" ... print 'Called example function' ... >>> example() Calling decorated function Called example function >>> example.__name__ 'example' >>> example.__doc__ 'Docstring'
可以看到最終調用的 example() 函數是經過 @my_decorator 裝飾的,裝飾器的作用是接受一個被包裹函數作為參數,對其進行加工,返回一個包裹函數。代碼使用 @functools.wraps 裝飾將要返回的包裹函數 wrapper,使得他的 __name__, __doc__ 和 __module__ 屬性與被裝飾函數 examle()完全相同, 這樣雖然最終調用的是經過裝飾的 example() 函數,但是某些屬性還是得到了維護。
如果在 @my_decorator 的定義中不使用 @functools.wraps 裝飾包裹函數,那么最終 example.__name__ 將會變為 ‘wrapper’, 而 example.__doc__ 也會丟失。
partial對象是調用partial()時創建的可調用對象,他們有三個只讀的屬性:
可調用或函數,調用partial對象時,會結合新的參數和關鍵字最終調用func。
默認為最左的位置參數,這些參數會被自動添加到所有調用partial對象時傳入的參數前。也就是說在調用partial對象時不用傳入這些參數即可,他們視為恆定的,從而自動添加到func的調用中。
當調用partial對象時提供的關鍵字參數。
partial對象在一些方面類似於函數對象:可調用,弱引用,可以擁有屬性。但是也有一些關鍵的區別:
1.partial對象的 __name__ 和 __doc__ 屬性不會自動創建;
2. 在類里定義的partial對象使用時更像靜態方法,在實例的屬性查詢過程中不會轉變成綁定方法(bound methods, 通過類的實例對象進行屬性引用)。