1. 程式人生 > >Python標準庫—Itertools

Python標準庫—Itertools

Itertools模組官方描述:
Functional tools for creating and using iterators.即用於建立高效迭代器的函式。
itertools用於高效迴圈的迭代函式集合。

迭代器
迭代器(生成器) 在Python中是一種很常用也很好用的資料結構,比起列表(list)來說,迭代器最大的優勢就是延遲計算,按需使用,從而提高開發體驗和執行效率,以至於在Python 3中map,filter等操作返回的不再是列表而是迭代器。

話雖這麼說但大家平時用到的迭代器大概只有range了,而通過iter函式把列表物件轉化為迭代器物件又有點多此一舉,這時候我們今天的主角itertools就該上場了。

迭代器的特點
惰性求值(Lazy evaluation),即只有當迭代至某個值時,它才會被計算,這個特點使得迭代器特別適合於遍歷大檔案或無限集合等,因為我們不用一次性將它們儲存在記憶體中。

使用itertools
itertools中的函式大多是返回各種迭代器物件,其中很多函式的作用我們平時要寫很多程式碼才能達到,而在執行效率上反而更低,畢竟人家是系統庫。
什麼是itertools
itertools 模組包含了一系列用來產生不同型別迭代器的函式或類,這些函式的返回都是一個迭代器,我們可以通過 for 迴圈來遍歷取值,也可以使用 next() 來取值。

itertools的分類

itertools 模組提供的迭代器函式有以下幾種型別:

  • 無限迭代器:生成一個無限序列,比如自然數序列 1, 2, 3, 4, …;
  • 有限迭代器:接收一個或多個序列(sequence)作為引數,進行組合、分組和過濾等;
  • 組合生成器:序列的排列、組合,求序列的笛卡兒積等;

無限迭代器

itertools 模組提供了三個函式(事實上,它們是類)用於生成一個無限序列迭代器:

函式 說明
count(firstval=0, step=1) 建立一個從 firstval (預設值為 0) 開始,以 step (預設值為 1) 為步長的的無限整數迭代器
cycle(iterable) 對 iterable 中的元素反覆執行迴圈,返回迭代器
repeat(object [,times] 反覆生成 object,如果給定 times,則重複次數為 times,否則為無限

詳解

1、itertools.count

就是一個計數器,可以指定起始位置和步長

##(1)引數不指定
# x= itertools.count()
# for i in x:
#     if i > 6:
#          break
#     print(i)

## (2)指定開始值和步長
# x= itertools.count(2, 3)
# for i in x:
#     if i > 6:
#          break
#     print(i)

##(3)也可用於切片操作:
# islice(iterable, [start, ] stop [, step])
# x = itertools.count(start=20, step=-1)
# print(list(itertools.islice(x, 0, 10, 1)))

2、itertools.cycle

迴圈指定的列表和迭代器,用於對 iterable 中的元素反覆執行迴圈.

##(1)迴圈語句
cycle_strings = itertools.cycle('ABC')
i = 1
for string in cycle_strings:
     if i == 10:
         break
     print(i, string)
     i += 1

##(2)也可用於切片操作
x = itertools.cycle('ABC')
print(list(itertools.islice(x, 0, 10, 1)))

3、itertools.repeat

簡單的生成一個擁有指定數目元素的迭代器

##(1)
x = itertools.repeat(3, 6)
print(list(x))

##(2)
for item in itertools.repeat('hello world', 3):
    print(item)

有限迭代器

itertools 模組提供了多個函式(類),接收一個或多個迭代物件作為引數,對它們進行組合、分組和過濾等:

序號 函式 語法 說明
1 chain() chain(iterable1, iterable2, iterable3, …) 連線多個列表或者迭代器,作為一個新的迭代器返回。
2 compress() compress(data, selectors) 用於對資料進行篩選,當 selectors 的某個元素為 true 時,則保留 data 對應位置的元素,否則去除.
3 dropwhile() dropwhile(predicate, iterable) 按照真值函式丟棄掉列表和迭代器前面的元素,iterable 中的元素,如果 predicate(item) 為 true,則丟棄該元素,否則返回該項及所有後續項。
4 groupby() groupby(iterable[, keyfunc]) iterable 是一個可迭代物件, keyfunc 是分組函式,用於對 iterable 的連續項進行分組,如果不指定,則預設對 iterable 中的連續相同項進行分組,返回一個 (key, sub-iterator) 的迭代器。
5 islice() islice(iterable, [start,] stop [, step]) 切片選擇,iterable 是可迭代物件,start 是開始索引,stop 是結束索引,step 是步長,start 和 step 可選。
6 tee() tee(iterable [,n]) 用於從 iterable 建立 n 個獨立的迭代器,以元組的形式返回,n 的預設值是 2。
7 takewhile() takewhile(predicate, iterable) predicate(item) 為 true,則保留該元素,只要 predicate(item) 為 false,則立即停止迭代。

詳解

1、itertools.chain

連線多個列表或者迭代器。
chain使用形式:

chain(iterable1, iterable2, iterable3, ...)

chain 接收多個可迭代物件作為引數,將它們【連線】起來,作為一個新的迭代器返回。

##(1)
x = itertools.chain(range(3), range(4), [3, 2, 4])
print(list(x))

##(2)
for item in itertools.chain([1, 2, 3], ['a', 'b', 'c']):
    print(item)

2、itertools.compress

按照真值表篩選元素。
語法:compress(data, selectors)
當 selectors 的某個元素為 true 時,則保留 data 對應位置的元素,否則去除。

x = itertools.compress(range(5), (True, False, True, True, False))
print(list(x))

x1 = list(itertools.compress('ABCDEF', [1, 1, 0, 1, 0, 1]))
print(x1)

x2 = list(itertools.compress('ABCDEF', [1, 1, 0, 1]))
print(x2)

x3 = list(itertools.compress('ABCDEF', [True, False, True]))
print(x3)

3、itertools.dropwhile

按照真值函式丟棄掉列表和迭代器前面的元素
語法:dropwhile(predicate, iterable)
predicate 是函式,iterable 是可迭代物件。對於 iterable 中的元素,如果 predicate(item) 為 true,則丟棄該元素,否則返回該項及所有後續項。

x = itertools.dropwhile(lambda e: e < 5, range(10))
print(list(x))

x1 = list(itertools.dropwhile(lambda x: x < 5, [1, 3, 6, 2, 1]))
print(x1)

x2 = list(itertools.dropwhile(lambda x2: x2 > 3, [2, 1, 6, 5, 4]))
print(x2)
---->
[5, 6, 7, 8, 9]
[6, 2, 1]
[2, 1, 6, 5, 4]

4、groupby

用於對序列進行分組。
語法:groupby(iterable[, keyfunc])
其中,iterable 是一個可迭代物件, keyfunc 是分組函式,用於對 iterable 的連續項進行分組,如果不指定,則預設對 iterable 中的連續相同項進行分組,返回一個 (key, sub-iterator) 的迭代器。

#(1)不指定分組
for key, value_iter in itertools.groupby('aaabbbaaccd'):
    print(key, ":", list(value_iter))

#(2)指定分組--使用 len 函式作為分組函式,連續項不相同
data = ['a', 'bb', 'ccc', 'dd', 'eee', 'f']
for key, value_iter in itertools.groupby(data, len):
    print(key, ":", list(value_iter))

#(3)指定分組--使用 len 函式作為分組函式,連續項相同
data = ['a', 'bb', 'cc', 'ddd', 'eee', 'f']
for key, value_iter in itertools.groupby(data, len):
    print(key, ";", list(value_iter))

5、islice

切片選擇
語法:islice(iterable, [start,] stop [, step])
iterable 是可迭代物件,start 是開始索引,stop 是結束索引,step 是步長,start 和 step 可選。

x = list(itertools.islice([10, 6, 2, 8, 1, 3, 9], 5))
print(x)

x1 = list(itertools.islice(itertools.count(), 6))
print(x1)

x2 = list(itertools.islice(itertools.count(), 3, 10))
print(x2)

x3 = list(itertools.islice(itertools.count(), 3, 10, 2))
print(x3)
---->
[10, 6, 2, 8, 1]
[0, 1, 2, 3, 4, 5]
[3, 4, 5, 6, 7, 8, 9]
[3, 5, 7, 9]

6、tee

生成指定數目的迭代器。
語法:tee(iterable [,n])
tee 用於從 iterable 建立 n 個獨立的迭代器,以元組的形式返回,n 的預設值是 2。

#(1)n 預設為 2,建立2個獨立的迭代器
x = itertools.tee('abcd')
print(x)

#(2)
x1, x2 = itertools.tee('abcde')
print(list(x1))
print(list(x2))

#(3)建立3個獨立的迭代器
x3 = itertools.tee('abc', 3)
print(x3)
---->
(<itertools._tee object at 0x000001ABBD283108>, <itertools._tee object at 0x000001ABBD283148>)
['a', 'b', 'c', 'd', 'e']
['a', 'b', 'c', 'd', 'e']
(<itertools._tee object at 0x000001ABBD2832C8>, <itertools._tee object at 0x000001ABBD283308>, <itertools._tee object at 0x000001ABBD283348>)

(4)
x4 = itertools.tee(range(10), 3)
for num in x4:
    print(list(num))
---->
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

7、takewhile

語法:takewhile(predicate, iterable)
predicate 是函式,iterable 是可迭代物件。如果 predicate(item) 為 true,則保留該元素,只要 predicate(item) 為 false,則立即停止迭代。

x = list(itertools.takewhile(lambda x: x < 5, [1, 3, 6, 2, 1]))
print(x)
x1 = list(itertools.takewhile(lambda x: x > 3, [2, 1, 6, 5, 4]))
print(x1)
---->
[1, 3]
[]

組合生成器

itertools 組合生成器函式,用於求序列的排列、組合等:

序號 函式 語法 說明
1 product product(iter1, iter2, … iterN, [repeat=1]) 用於求多個可迭代物件的笛卡爾積,它跟巢狀的 for 迴圈等價。repeat 是一個關鍵字引數,用於指定重複生成序列的次數。
2 permutations permutations(iterable[, r]) 用於生成一個排列,r 指定生成排列的元素的長度,如果不指定,則預設為可迭代物件的元素長度。
3 combinations combinations(iterable, r) 用於求序列的組合,r 指定生成組合的元素的長度。
4 combinations_with_replacement combinations_with_replacement(iterable, r) 和 combinations 類似,但它生成的組合包含自身元素。

詳解

1、product

product 用於求多個可迭代物件的笛卡爾積,它跟巢狀的 for 迴圈等價。
語法:product(iter1, iter2, ... iterN, [repeat=1])
repeat是一個關鍵字引數,用於指定重複生成序列的次數,

for item in itertools.product('ABCD', 'xy'):
    print(item)

x = list(itertools.product('ab', range(3)))
print(x)

x1 = list(itertools.product((0, 1), (0, 1), (0, 1)))
print(x1)

x2 = list(itertools.product('ABC', repeat=2))
print(x2)

2、permutations

permutations 用於生成一個排列。
語法:permutations(iterable[, r])
r 指定生成排列的元素的長度,如果不指定,則預設為可迭代物件的元素長度。

x1 = list(itertools.permutations('ABC', 2))
print(x1)

x2 = list(itertools.permutations('ABC'))
print(x2)
---->
[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
[('A', 'B', 'C'), ('A', 'C', 'B'), ('B', 'A', 'C'), ('B', 'C', 'A'), ('C', 'A', 'B'), ('C', 'B', 'A')]

3、combinations 用於求序列的組合

語法:combinations(iterable, r)
其中,r 指定生成組合的元素的長度。

x = list(itertools.combinations('ABC', 2))
print(x)
---->
[('A', 'B'), ('A', 'C'), ('B', 'C')]

4、combinations_with_replacement

和 combinations 類似,但它生成的組合包含自身元素。

x = list(itertools.combinations_with_replacement('ABC', 2))
print(x)
---->
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]

小結

itertools模組提供了很多用於產生多種型別迭代器的函式,它們的返回值不是 list,而是迭代器。