Python標準庫之functools/itertools/operator

發表於2017-01-22

引言

functools, itertools, operator是Python標準庫為我們提供的支援函數語言程式設計的三大模組,合理的使用這三個模組,我們可以寫出更加簡潔可讀的Pythonic程式碼,接下來我們通過一些example來了解三大模組的使用。

functools的使用

functools是Python中很重要的模組,它提供了一些非常有用的高階函式。高階函式就是說一個可以接受函式作為引數或者以函式作為返回值的函式,因為Python中函式也是物件,因此很容易支援這樣的函式式特性

partial

basetwo('10010')實際上等價於呼叫int('10010', base=2),當函式的引數個數太多的時候,可以通過使用functools.partial來建立一個新的函式來簡化邏輯從而增強程式碼的可讀性,而partial內部實際上就是通過一個簡單的閉包來實現的。

partialmethod

partialmethod和partial類似,但是對於繫結一個非物件自身的方法的時候,這個時候就只能使用partialmethod了,我們通過下面這個例子來看一下兩者的差異。

singledispatch

雖然Python不支援同名方法允許有不同的引數型別,但是我們可以借用singledispatch來動態指定相應的方法所接收的引數型別,而不用把引數判斷放到方法內部去判斷從而降低程式碼的可讀性。

下面通過@test_method.register(int)和@test_method.register(list)指定當test_method的第一個引數為int或者list的時候,分別呼叫不同的方法來進行處理

wraps

裝飾器會遺失被裝飾函式的__name__和__doc__等屬性,可以使用@wraps來恢復。

我們也可以使用update_wrapper來改寫。

@wraps內部實際上就是基於update_wrapper來實現的。

total_ordering

Python2中可以通過自定義__cmp__的返回值0/-1/1來比較物件的大小,在Python3中廢棄了__cmp__,但是我們可以通過totalordering然後修改 _lt__() , __le__() , __gt__(), __ge__(), __eq__(), __ne__() 等魔術方法來自定義類的比較規則。p.s: 如果使用必須在類裡面定義 __lt__() , __le__() , __gt__(), __ge__()中的一個,以及給類新增一個__eq__() 方法。

下面是執行結果:

itertools的使用

itertools為我們提供了非常有用的用於操作迭代物件的函式

無限迭代器

count

count(start=0, step=1) 會返回一個無限的整數iterator,每次增加1。可以選擇提供起始編號,預設為0。

cycle

cycle(iterable) 會把傳入的一個序列無限重複下去,不過可以提供第二個引數就可以制定重複次數。

repeat

repeat(object[, times]) 返回一個元素無限重複下去的iterator,可以提供第二個引數就可以限定重複次數。

Iterators terminating on the shortest input sequence

accumulate

accumulate(iterable[, func])

chain

itertools.chain(*iterables)可以將多個iterable組合成一個iterator。

chain的實現原理如下:

chain.from_iterable

chain.from_iterable(iterable)和chain類似,但是隻是接收單個iterable,然後將這個iterable中的元素組合成一個iterator。

實現原理也和chain類似。

compress

compress(data, selectors)接收兩個iterable作為引數,只返回selectors中對應的元素為True的data,當data/selectors之一用盡時停止。

zip_longest

zip_longest(*iterables, fillvalue=None)和zip類似,但是zip的缺陷是iterable中的某一個元素被遍歷完,整個遍歷都會停止,具體差異請看下面這個例子:

下面是輸出結果:

islice

islice(iterable, stop) or islice(iterable, start, stop[, step]) 與Python的字串和列表切片有一些類似,只是不能對start、start和step使用負值。

tee

tee(iterable, n=2) 返回n個獨立的iterator,n預設為2。

下面是輸出結果,注意tee(r)後,r作為iterator已經失效,所以for迴圈沒有輸出值:

starmap

starmap(func, iterable)假設iterable將返回一個元組流,並使用這些元組作為引數呼叫func:

filterfalse

filterfalse(predicate, iterable) 與filter()相反,返回所有predicate返回False的元素

takewhile

takewhile(predicate, iterable) 只要predicate返回True,不停地返回iterable中的元素。一旦predicate返回False,iteration將結束。

dropwhile

dropwhile(predicate, iterable) 在predicate返回True時捨棄元素,然後返回其餘迭代結果:、

groupby

groupby(iterable, key=None) 把iterator中相鄰的重複元素挑出來放在一起。p.s: The input sequence needs to be sorted on the key value in order for the groupings to work out as expected.

  • [k for k, g in groupby(‘AAAABBBCCDAABBB’)] –> A B C D A B
  • [list(g) for k, g in groupby(‘AAAABBBCCD’)] –> AAAA BBB CC D

Combinatoric generators

product

product(*iterables, repeat=1)

  • product(A, B) returns the same as ((x,y) for x in A for y in B)
  • product(A, repeat=4) means the same as product(A, A, A, A)

permutations

permutations(iterable, r=None)返回長度為r的所有可能的組合:

下面是輸出結果:

combinations

combinations(iterable, r) 返回一個iterator,提供iterable中所有元素可能組合的r元組。每個元組中的元素保持與iterable返回的順序相同。下面的例項中,不同於上面的permutations,a總是在bcd之前,b總是在cd之前,c總是在d之前。

下面是輸出結果:

combinations_with_replacement

combinations_with_replacement(iterable, r)函式放寬了一個不同的約束:元素可以在單個元組中重複,即可以出現aa/bb/cc/dd等組合:

下面是輸出結果:

operator的使用

attrgetter

operator.attrgetter(attr)和operator.attrgetter(*attrs)

  • After f = attrgetter(‘name’), the call f(b) returns b.name.
  • After f = attrgetter(‘name’, ‘date’), the call f(b) returns (b.name, b.date).
  • After f = attrgetter(‘name.first’, ‘name.last’), the call f(b) returns (b.name.first, b.name.last).

我們通過下面這個例子來了解一下itergetter的用法:

attrgetter的實現原理:

itemgetter

operator.itemgetter(item)和operator.itemgetter(*items)

  • After f = itemgetter(2), the call f(r) returns r[2].
  • After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]).

我們通過下面這個例子來了解一下itergetter的用法:

itemgetter的實現原理

methodcaller

operator.methodcaller(name[, args…])

  • After f = methodcaller(‘name’), the call f(b) returns b.name().
  • After f = methodcaller(‘name’, ‘foo’, bar=1), the call f(b) returns b.name(‘foo’, bar=1).

methodcaller的實現原理:

References

DOCUMENTATION-FUNCTOOLS
DOCUMENTATION-ITERTOOLS
DOCUMENTATION-OPERATOR
HWOTO-FUNCTIONAL
HWOTO-SORTING
PYMOTW

相關文章