functools模塊用于高階函數(shù):作用與或者返回其它函數(shù)的函數(shù)袒餐。一般來說,對于該模塊,任何可調(diào)用對象都可以視為一個函數(shù)
[TOC]
cmp_to_key
Help on function cmp_to_key in module functools:
cmp_to_key(mycmp)
Convert a cmp= function into a key= function
幫助文檔說的很簡單 將 比較函數(shù)轉(zhuǎn)換為key函數(shù),這就引出三個問題1:什么是比較函數(shù);2:什么是key函數(shù);3:怎么將cmp函數(shù)轉(zhuǎn)為key函數(shù);3:為什么要py3要取消cmp函數(shù)
-
什么是比較函數(shù)
py3中取消了cmp函數(shù) 而這個函數(shù)在py2中是BIF,定義如下:
Help on built-in function cmp in module __builtin__: cmp(...) cmp(x, y) -> integer Return negative if x<y, zero if x==y, positive if x>y.
如果是x小于y則返回一個負(fù)數(shù);如果z>y則返回一個正數(shù);如果x==y則返回0
什么是
key函數(shù)
key函數(shù)接受一個參數(shù),返回一個可以用作排序的關(guān)鍵字(有點感覺是hash了)-
怎么將
cmp函數(shù)
轉(zhuǎn)為key函數(shù)
- 因為
python3
不存在cm
p函數(shù)了呀 導(dǎo)致很多函數(shù)不支持cmp
了 比如看sorted
的幫助文檔:- py2
Help on built-in function sorted in module __builtin__: sorted(...) sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list
- py3
Help on built-in function sorted in module builtins: sorted(iterable, key=None, reverse=False) Return a new list containing all items from the iterable in ascending order. A custom key function can be supplied to customise the sort order, and the reverse flag can be set to request the result in descending order.
- py2
- 很簡單 在py2設(shè)計過一個cmp函數(shù)了,但是到py3不能用了怎么辦?用
functools.cmp_to_key
啊:- 對序列
a=range(10)
進(jìn)行排序 - 首先定義一個比較函數(shù):比較x+4和y的大小關(guān)系
>>> cmp_func = lambda x,y: x+4 >y >>> cmp_func(3,10) False >>> cmp_func(3,1) True >>> cmp_func(3,7) False >>> cmp_func(3,6) True
- py2 排序的時候直接用cmp參數(shù)
>>> sorted(a, cmp=cmp_func) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- py3沒有cmp參數(shù) 只有key參數(shù)
# 當(dāng)然py2中也是可以采用這種方法的 >>> sorted(a, key=functools.cmp_to_key(cmp_func)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- 對序列
- 參考Chi's Blog網(wǎng)站中的文章Python3中排序的cmp函數(shù)的替代方法
- 因為
## functools.reduce
> functools.reduce 和BIF reduce的功能很相似
以下是兩種方法的定義
- functools.reduce
```
Help on built-in function reduce in module _functools:
reduce(...)
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
```
- reduce
```
Help on built-in function reduce in module __builtin__:
reduce(...)
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
```
可以看到兩個方法連定義都一模一樣, 但是以上是在python2中的測試結(jié)果,在python3中是沒有reduce這個BIF的,這就是這兩個函數(shù)的本質(zhì)區(qū)別: **引入functools.reduce就是為了兼容python3的**,下面就以reduce說明一下功能:
> 對序列`sequence`連續(xù)使用函數(shù)`function`;如果給出 初始值`initial`,會首先將initial加到`sequence`的頭部;第一次將序列的頭兩個元素進(jìn)行`function`計算,以后每次都是使用前一次的計算結(jié)果和下一個元素進(jìn)行計算
- 無初始值
```
>>> reduce(lambda x,y:x*y, xrange(1,6))
120
>>>
```
- 有初始值
```
>>> reduce(lambda x,y:x*y, xrange(1,6), 10)
1200
>>>
```
## functools.total_ordering
類裝飾器 當(dāng)你需要自定義一個類的比較方法時,默認(rèn)你需要定義 等于eq 大于gt 小于lt 大于等于ge 小于等于le 有可能還要定義不等于(ne) 但是如果適用了這個類裝飾器 那么只需要定義 eq 和 lt le gt ge中的一個就好了
@functools.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()))
print(dir(Student))
# ['__doc__', '__eq__', '__ge__', '__gt__', '__le__', '__lt__', '__module__']
partial
偏函數(shù) 最常用的應(yīng)用場景是固定一個函數(shù)的某些參數(shù)
如果有大量二進(jìn)制轉(zhuǎn)換任務(wù),我們可能定義一個in2函數(shù)
>>> int('10010', base=2)
18
>>> def in2(x, base=2):
... return int(x, base)
...
>>> in2('1010')
10
但是我們也可以直接簡單生成
>>> in22 = functools.partial(int, base=2)
>>> in22('11001')
25
partialmethod
類似于 partial 但是 只有 partialmethod才能作用于方法
lru_cache
緩存函數(shù)的運(yùn)行結(jié)果:遞歸求斐波拉切數(shù)列時可以緩存某個結(jié)果;緩存網(wǎng)絡(luò)請求等
lru_cache(maxsize=128, typed=False)
maxsize是指定最大緩存數(shù)量, typed則代表是否嚴(yán)格判斷類型如果設(shè)置為False,則參數(shù)3.0不能使用參數(shù)為3的緩存
update_wrapper
update_wrapper 類似于 wraps 甚至
@wraps
內(nèi)部實際上就是基于update_wrapper來實現(xiàn)的
def wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES):
def decorator(wrapper):
return update_wrapper(wrapper, wrapped=wrapped...)
return decorator
wraps
裝飾器會遺失被裝飾函數(shù)的name和doc等屬性,可以使用@wraps 來恢復(fù)
singledispatch
JAVA等語言可以類的重載场仲,可以為同一個方法不同類型參數(shù)執(zhí)行不同的方法, 但Python不支持同名方法有不同的參數(shù)類型,python給我們的解決方案是使用 singledispatch 來動態(tài)指定相應(yīng)的方法所接收的參數(shù)類型退疫,而不用把參數(shù)判斷放到方法內(nèi)部去判斷從而降低代碼的可讀性