Python中 itertools模塊創建高效迭代器、處理序列數據集。
此模塊所有函數返回迭代器,可用for循環獲取迭代器中的內容,也可用list(...)用列表形式顯示內容。
import itertools[ x for x in dir(itertools) if not x.startswith('_')]
# 結果:
['accumulate', 'chain', 'combinations', 'combinations_with_replacement',
'compress', 'count', 'cycle', 'dropwhile', 'filterfalse', 'groupby',
'islice', 'pairwise', 'permutations', 'product', 'repeat', 'starmap',
'takewhile', 'tee', 'zip_longest']
【Python】itertools模塊
1、chain 【鏈接多個可迭代對象】
chain(可迭代對象1, 可迭代對象2, ...):返回一個迭代器,包含參數中的所有可迭代對象的內容。
from itertools import *a = [1,2,3,4,5]
b = ["a","b","c","d","e"]chain(a,b) # 結果:<itertools.chain object at 0x0000020AD8E77010>
list(chain(a,b)) # 結果:[1, 2, 3, 4, 5, 'a', 'b', 'c', 'd', 'e']
# 或者
for x in chain(a,b):print(x)
# 結果:
1
2
3
4
5
a
b
c
d
e
若不能提前確定所有可迭代對象,或需要懶方法計算,則使用chain.from_iterable(...)。
from itertools import *# 有yield的函數視為生成器,需用next()方法或for循環才開始執行函數。(控制內存占用,且簡潔)
def new_iterable():yield [1,2,3]yield ["a","b","c"]for x in chain.from_iterable(new_iterable()):print(x)
# 結果:
1
2
3
a
b
c
2、zip_longest 【類似zip】
內置函數zip()。
zip(可迭代對象1, 可迭代對象2, ...):返回一個迭代器,將多個可迭代對象中的元素,按對應位置一一組成元組形式。若其中一個可迭代對象處理完,則停止。
from itertools import *a = [1,2,3]
b = ["a","b","c","d","e"]list(zip(a,b)) # 結果:[(1, 'a'), (2, 'b'), (3, 'c')]
zip_longest(可迭代對象1, 可迭代對象2, ...):類似zip。但將所有可迭代對象處理完,若有缺失值則用None填充。可用fillvalue參數指定空缺默認值。
from itertools import *a = [1,2,3]
b = ["a","b","c","d","e"]list(zip_longest(a,b))
# 結果:[(1, 'a'), (2, 'b'), (3, 'c'), (None, 'd'), (None, 'e')]
list(zip_longest(a,b,fillvalue=999))
# 結果:[(1, 'a'), (2, 'b'), (3, 'c'), (999, 'd'), (999, 'e')]
3、starmap 【類似map】
內置函數map()。
map(函數,可迭代對象1, 可迭代對象2, ...):返回一個迭代器,將多個可迭代對象中的元素,依次調用函數處理。若其中一個可迭代對象處理完,則停止。
注:多個可迭代對象,是函數中涉及多個可迭代對象。若函數中只涉及一個可迭代對象,則map參數中只能有一個可迭代對象。
from itertools import *a = [1,2,3,4,5]
list(map(lambda x:x**3,a)) # 結果:[1, 8, 27, 64, 125]a = "hello"
b = "world world"
list(map(lambda x,y:(x,y,x+y),a,b))
# 結果:[('h', 'w', 'hw'), ('e', 'o', 'eo'), ('l', 'r', 'lr'), ('l', 'l', 'll'), ('o', 'd', 'od')]for value in map(lambda x,y:(x,y,x+y),a,b):print('{}+{}->{}'.format(*value))
# 或者
# for x,y,z in map(lambda x,y:(x,y,x+y),a,b):
# print('{}+{}->{}'.format(x,y,z))
# 結果:
h+w->hw
e+o->eo
l+r->lr
l+l->ll
o+d->od
starmap(函數,可迭代對象):類似map()。區別是:map中的參數是函數和一個或多個可迭代對象,將可迭代對象的每個元素作為單個參數傳遞給函數即fun(a,b);而starmap中的參數是函數和一個元組形式的可迭代對象,將可迭代對象的每個元組解包成多個參數傳遞給函數即fun(*c)。
from itertools import *c = [('h', 'w'), ('e', 'o'), ('l', 'r'), ('l', 'l'), ('o', 'd')]
list(starmap(lambda x,y:(x,y,x+y),c))
# 結果:[('h', 'w', 'hw'), ('e', 'o', 'eo'), ('l', 'r', 'lr'), ('l', 'l', 'll'), ('o', 'd', 'od')]for x in starmap(lambda x,y:(x,y,x+y),c):print(x)
# 結果:
('h', 'w', 'hw')
('e', 'o', 'eo')
('l', 'r', 'lr')
('l', 'l', 'll')
('o', 'd', 'od')for value in starmap(lambda x,y:(x,y,x+y),c):print('{}+{}->{}'.format(*value))
# 或者
# for x,y,z in starmap(lambda x,y:(x,y,x+y),c):
# print('{}+{}->{}'.format(x,y,z))
# 結果:
h+w->hw
e+o->eo
l+r->lr
l+l->ll
o+d->od
4、islice 【類似切片】
- islice(可迭代對象, end):返回一個迭代器,從可迭代對象中獲取從0到end(不含)的元素。
- islice(可迭代對象, start, end):返回一個迭代器,從可迭代對象中獲取起始位置start(含)到結束位置end(不含)的元素。若end是None,則一直到可迭代對象結束。
- islice(可迭代對象, start, end, step):返回一個迭代器,從可迭代對象中獲取起始位置start(含)到結束位置end(不含)且步長間隔step的元素。若end是None,則一直到可迭代對象結束。
from itertools import *list(islice(range(10),5)) # 結果:[0, 1, 2, 3, 4]
list(islice(range(10),5,8)) # 結果:[5, 6, 7]
list(islice(range(10),5,None)) # 結果:[5, 6, 7, 8, 9]
list(islice(range(10),0,8,2)) # 結果:[0, 2, 4, 6]
list(islice(range(10),0,None,2)) # 結果:[0, 2, 4, 6, 8]
?5、accumulate 【累加和】
- accumulate(可迭代對象):返回一個迭代器,對每個元素依次進行累加和并返回結果。
- accumulate(可迭代對象, initial=num):返回一個迭代器,在num基礎上再對每個元素依次進行累加和并返回結果。
- accumulate(可迭代對象,?函數):返回一個迭代器,對每個元素依次調用函數并返回結果。
from itertools import *
import operatorlist(accumulate(range(10))) # 結果:[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
list(accumulate("abcdefg")) # 結果:['a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef', 'abcdefg']# 在100的基礎上,再進行0-9累加和
list(accumulate(range(10),initial=100)) # 結果:[100, 100, 101, 103, 106, 110, 115, 121, 128, 136, 145]# 1-5累積相乘
list(accumulate(range(1,6),operator.mul)) # 結果:[1, 2, 6, 24, 120]
6、count 【無限生成連續的整數】
- count():返回一個迭代器,無限生成連續的整數,從0開始。
- count(start):返回一個迭代器,無限生成連續的整數,從start開始。
- count(start,step):返回一個迭代器,無限生成連續的整數,從start開始步長間隔step。
from itertools import *for x in zip(count(),["ab","cd","ef"]):print(x)
# 結果:
(0, 'ab')
(1, 'cd')
(2, 'ef')list(islice(count(1,4),5)) # 結果:[1, 5, 9, 13, 17]
注解:zip()最短的可迭代對象處理完就停止。count()無限生成連續的整數,但["ab","cd","ef"]長度只有3,處理完就停止。
7、cycle? 【無限循環】
cycle(可迭代對象):?返回一個迭代器,將可迭代對象無限循環。
from itertools import *list(zip(range(10),cycle("good")))
# 結果:
[(0, 'g'), (1, 'o'), (2, 'o'), (3, 'd'), (4, 'g'), (5, 'o'), (6, 'o'), (7, 'd'), (8, 'g'), (9, 'o')]list(zip(range(10),cycle(["a","b"])))
# 結果:
[(0, 'a'), (1, 'b'), (2, 'a'), (3, 'b'), (4, 'a'), (5, 'b'), (6, 'a'), (7, 'b'), (8, 'a'), (9, 'b')]
8、repeat 【重復】
?repeat(需重復的數據, num):返回一個迭代器,重復num次。
repeat(n):也可為map或zip提供常量值流(a stream of constant values)。
from itertools import *
from operator import powlist(repeat('abc', 5)) # 結果:['abc', 'abc', 'abc', 'abc', 'abc']
list(repeat(1,5)) # 結果:[1, 1, 1, 1, 1]# 將列表中的數字求3次冪,num**3
a = [1,2,3]
list(map(pow,a,repeat(3))) # 結果:[1, 8, 27]
9、product 【笛卡爾積】
- product(可迭代對象1,?可迭代對象2, ...):返回一個迭代器,將多個可迭代對象中的元素依次一一組成元組。
- product(可迭代對象, repeat=num):返回一個迭代器,將一個可迭代對象和自身進行笛卡爾積。
from itertools import *a = [1,2,3]
b = ["a","b"]
c = "hello"
list(product(a,b,c))
# 結果:
[(1, 'a', 'h'), (1, 'a', 'e'), (1, 'a', 'l'), (1, 'a', 'l'), (1, 'a', 'o'),
(1, 'b', 'h'), (1, 'b', 'e'), (1, 'b', 'l'), (1, 'b', 'l'), (1, 'b', 'o'),
(2, 'a', 'h'), (2, 'a', 'e'), (2, 'a', 'l'), (2, 'a', 'l'), (2, 'a', 'o'),
(2, 'b', 'h'), (2, 'b', 'e'), (2, 'b', 'l'), (2, 'b', 'l'), (2, 'b', 'o'),
(3, 'a', 'h'), (3, 'a', 'e'), (3, 'a', 'l'), (3, 'a', 'l'), (3, 'a', 'o'),
(3, 'b', 'h'), (3, 'b', 'e'), (3, 'b', 'l'), (3, 'b', 'l'), (3, 'b', 'o')]a = [1,2,3]
list(product(a, repeat=2)) # 相當于 list(product(a,a))
# 結果:
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
10、permutations 【指定長度的排列組合】
permutations(可迭代對象):返回一個迭代器,將元素重新排列且長度為可迭代對象的長度的所有組合,組合以元組形式。
permutations(可迭代對象, n):返回一個迭代器,將元素重新排列且長度為n的所有組合,組合以元組形式。
from itertools import *a = [1,2,3]
list(permutations(a))
# 結果:
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]list(permutations(a,2))
# 結果:
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
11、combinations 【指定長度的排列組合,沒有重復值】
combinations(可迭代對象,r=num):類似permutations。但組合中沒有重復值(重復值為元組中元素相同但元素順序不同,例如(1,2)和(2,1)為重復值)。
注意:r參數為必需參數,指定長度。
from itertools import *a = [1,2,3]
list(combinations(a,r=2)) # 結果:[(1, 2), (1, 3), (2, 3)]
list(combinations(a,2)) # 結果:[(1, 2), (1, 3), (2, 3)]
permutations_with_replacement(可迭代對象,r=num):類似combinations()。但有重復元素的組合(例如(1,1)和(2,2))。
from itertools import *a = [1,2,3]
list(combinations_with_replacement(a,r=2)) # 結果:[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
12、pairwise? 【依次生成連續的兩個元素】
pairwise(可迭代對象):返回一個迭代器,依次生成連續兩個元素的組合。若可迭代對象中的元素小于2個,則返回的迭代器為空。
from itertools import *a = [1,2,3,4,5,6]
list(pairwise(a)) # 結果:[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]b = "hello"
list(pairwise(b)) # 結果:[('h', 'e'), ('e', 'l'), ('l', 'l'), ('l', 'o')]c = "w"
list(pairwise(c)) # 結果:[]
13、takewhile【返回滿足條件的,舍棄第一個False之后的所有元素】
takewhile(predicate,?可迭代對象):返回一個迭代器,若predicate返回True,則返回該元素,一旦碰到predicate返回False,則終止。
from itertools import *a = [3,6,7,8,9]
list(takewhile(lambda x: x%3==0, a)) # 結果:[3, 6]
14、dropwhile【丟棄滿足條件的,返回第一個False之后的所有元素】
?dropwhile(predicate,?可迭代對象):返回一個迭代器,若predicate返回True,則丟棄該元素,一旦碰到predicate返回False,則終止,返回后面的全部元素。
from itertools import *a = [3,6,7,8,9]
list(dropwhile(lambda x: x%3==0, a)) # 結果:[7, 8, 9]
15、filterfalse 【只返回不滿足條件的元素】
內置函數filter()。
filtler(predicate,?可迭代對象):返回一個迭代器,只返回滿足條件的元素。
from itertools import *a = [3,6,7,8,9]
list(filter(lambda x: x%3==0, a)) # 結果:[3, 6, 9]
?filterfalse(predicate,?可迭代對象):返回一個迭代器,只返回不滿足條件的元素。
from itertools import *a = [3,6,7,8,9]
list(filterfalse(lambda x: x%3==0, a)) # 結果:[7, 8]
16、compress? 【通過選擇器,返回需要的數據】
compress(數據,?選擇器):以選擇器作為篩選,來返回數據中符合的數據。
from itertools import *a = [3,6,7,8,9]
b = cycle([False,True]) # 即 False,True, False,True, False,True...
list(compress(a, b)) # 結果:[6, 8]
17、groupby? 【分組】
groupby(可迭代對象,?分組內容):根據分組內容進行分組,返回一個迭代器,迭代器中的元素是元組,(分組內容,?以列表顯示對應的值)。
注意:分組之前,注意排序。
from itertools import *a = [1,2,2,3,1,2]
b = islice(count(),8)
ab = list(zip(a,b))
ab # 結果:[(1, 0), (2, 1), (2, 2), (3, 3), (1, 4), (2, 5)]for k,v in groupby(ab,lambda x:x[0]):print(k,list(v))
# 結果:
1 [(1, 0)]
2 [(2, 1), (2, 2)]
3 [(3, 3)]
1 [(1, 4)]
2 [(2, 5)] ab.sort()
ab # 結果:[(1, 0), (1, 4), (2, 1), (2, 2), (2, 5), (3, 3)]for k,v in groupby(ab,lambda x:x[0]):print(k,list(v))
# 結果:
1 [(1, 0), (1, 4)]
2 [(2, 1), (2, 2), (2, 5)]
3 [(3, 3)]
18、tee 【一個輸入分解成多個相同的輸出流】
變量1,?變量2,... = tee(可迭代對象, n=num):返回元組形式,元組中元素是迭代器。將一個輸入分解成num個相同的輸出流。默認n=2。類似于UNIX?tee工具。
注意:① 使用tee()生成新的迭代器,原來的可迭代對象不應再使用。
? ? ? ? ? ② tee()生成的迭代器,不是線程安全的,且需大量輔助存儲。
from itertools import *a = [1,2,3,4,5]m,n = tee(a) # 相當于 m,n = tee(a,2)
list(m) # 結果:[0, 1, 2, 3, 4, 5, 6, 7]
list(n) # 結果:[0, 1, 2, 3, 4, 5, 6, 7]
list(m) == list(n) # 結果:True
m is n # 結果:False
補充:可迭代對象、迭代器
可迭代對象:
滿足__iter__( )方法的對象。即可用for循環遍歷的對象。
例如:列表、字符串、文件等。
迭代器:
同時滿足__iter__( )方法和__next__( )方法的對象。即可用for循環遍歷又可用next()獲取下一個值的對象。
可迭代對象不一定是迭代器,迭代器一定是可迭代對象。
可迭代對象轉為迭代器:iter(可迭代對象)
判斷是否是可迭代對象:isinstance(對象, collections.abc.Iterable)
判斷是否是迭代器:isinstance(對象, collections.abc.Iterator)
from collections.abc import Iterator, Iterableisinstance("hello",Iterable) # 結果:True
isinstance("hello",Iterator) # 結果:Falseisinstance(iter("hello"),Iterator) # 結果:True
參考:Pydoc: built-in module itertools
?