1. 程式人生 > >itertools函式解析

itertools函式解析

原始網頁:https://www.cnblogs.com/fengshuihuan/p/7105545.html

這貨很強大, 必須掌握

文件 連結 http://docs.python.org/2/library/itertools.html

pymotw 連結 http://pymotw.com/2/itertools/

基本是基於文件的翻譯和補充,相當於翻譯了

itertools用於高效迴圈的迭代函式集合

組成

總體,整體瞭解

無限迭代器

複製程式碼程式碼如下:

 

1

2

3

4

迭代器         引數         結果                                                例子

count()     start, [step]   start, start+step, start+2*step, ...                count(10--10 11 12 13 14 ...

cycle()     p               p0, p1, ... plast, p0, p1, ...                      cycle(

'ABCD'--> A B C D A B C D ...

repeat()    elem [,n]       elem, elem, elem, ... endlessly or up to n times    repeat(103--10 10 10

  


處理輸入序列迭代器

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

迭代器          引數            結果                                        例子

chain()     p, q, ...           p0, p1, ... plast, q0, q1, ...              chain('ABC''DEF'--> A B C D E F

compress()  data, selectors     (d[0if s[0]), (d[1if s[1]), ...         compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F

dropwhile() pred, seq           seq[n], seq[n+1], starting when pred fails  dropwhile(lambda x: x<5, [1,4,6,4,1]) --6 4 1

groupby()   iterable[, keyfunc] sub-iterators grouped by value of keyfunc(v)

ifilter()   pred, seq           elements of seq where pred(elem) is True    ifilter(lambda x: x%2range(10)) --1 3 5 7 9

ifilterfalse()  pred, seq       elements of seq where pred(elem) is False   ifilterfalse(lambda x: x%2range(10)) --0 2 4 6 8

islice()    seq, [start,] stop [, step] elements from seq[start:stop:step]  islice('ABCDEFG'2None--> C D E F G

imap()      func, p, q, ...     func(p0, q0), func(p1, q1), ...             imap(pow, (2,3,10), (5,2,3)) --32 9 1000

starmap()   func, seq           func(*seq[0]), func(*seq[1]), ...           starmap(pow, [(2,5), (3,2), (10,3)]) --32 9 1000

tee()       it, n               it1, it2 , ... itn splits one iterator into n

takewhile() pred, seq           seq[0], seq[1], until pred fails            takewhile(lambda x: x<5, [1,4,6,4,1]) --1 4

izip()      p, q, ...           (p[0], q[0]), (p[1], q[1]), ...             izip('ABCD''xy'--> Ax By

izip_longest()  p, q, ...       (p[0], q[0]), (p[1], q[1]), ...             izip_longest('ABCD''xy', fillvalue='-'--> Ax By C- D-

  

 

組合生成器

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

迭代器          引數                        結果

product()       p, q, ... [repeat=1]        cartesian product, equivalent to a nested for-loop

permutations()  p[, r]                      r-length tuples, all possible orderings, no repeated elements

combinations()  p, r                        r-length tuples, in sorted order, no repeated elements

combinations_with_replacement() p, r        r-length tuples, in sorted order, with repeated elements

product('ABCD', repeat=2)                   AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD

permutations('ABCD'2)                     AB AC AD BA BC BD CA CB CD DA DB DC

combinations('ABCD'2)                     AB AC AD BC BD CD

combinations_with_replacement('ABCD'2)    AA AB AC AD BB BC BD CC CD DD

  

 

第一部分

 

itertools.count(start=0, step=1)

建立一個迭代器,生成從n開始的連續整數,如果忽略n,則從0開始計算(注意:此迭代器不支援長整數)

如果超出了sys.maxint,計數器將溢位並繼續從-sys.maxint-1開始計算。

定義

複製程式碼程式碼如下:

1

2

3

4

5

6

7

def count(start=0, step=1):

    # count(10) --> 10 11 12 13 14 ...

    # count(2.5, 0.5) -> 2.5 3.0 3.5 ...

    = start

    while True:

        yield n

        += step

  

等同於(start + step * i for i in count())

 

使用

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

from itertools import *

  

 

for in izip(count(1), ['a''b''c']):

    print i

 

(1'a')

(2'b')

(3'c')

  

itertools.repeat(object[, times])

建立一個迭代器,重複生成object,times(如果已提供)指定重複計數,如果未提供times,將無止盡返回該物件。

定義

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

def repeat(object, times=None):

    # repeat(10, 3) --> 10 10 10

    if times is None:

        while True:

            yield object

    else:

        for in xrange(times):

            yield object

 

使用

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

from itertools import *

  

 

for in repeat('over-and-over'5):

    print i

 

over-and-over

over-and-over

over-and-over

over-and-over

over-and-over

  

第二部分
itertools.chain(*iterables)

將多個迭代器作為引數, 但只返回單個迭代器, 它產生所有引數迭代器的內容, 就好像他們是來自於一個單一的序列.

複製程式碼程式碼如下:

1

2

3

4

5

def chain(*iterables):

    # chain('ABC', 'DEF') --> A B C D E F

    for it in iterables:

        for element in it:

            yield element

  

使用

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

from itertools import *

  

 

for in chain([123], ['a''b''c']):

    print i

1

2

3

a

b

c

 

 

from itertools import chain, imap

def flatmap(f, items):

    return chain.from_iterable(imap(f, items))

>>> list(flatmap(os.listdir, dirs))

>>> ['settings.py''wsgi.py''templates''app.py',

     'templates''index.html, 'config.json']

  

 

 

itertools.compress(data, selectors)

提供一個選擇列表,對原始資料進行篩選

複製程式碼程式碼如下:

 

1

2

3

4

def compress(data, selectors):

    # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F

    return (d for d, s in izip(data, selectors) if s)

itertools.dropwhile(predicate, iterable)

  


建立一個迭代器,只要函式predicate(item)為True,就丟棄iterable中的項,如果predicate返回False,就會生成iterable中的項和所有後續項。

 

即:在條件為false之後的第一次, 返回迭代器中剩下來的項.

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

9

10

def dropwhile(predicate, iterable):

    # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1

    iterable = iter(iterable)

    for in iterable:

        if not predicate(x):

            yield x

            break

    for in iterable:

        yield x

  

使用

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

from itertools import *

  

 

def should_drop(x):

    print 'Testing:', x

    return (x<1)

 

for in dropwhile(should_drop, [ -1012341-2 ]):

    print 'Yielding:', i

 

Testing: -1

Testing: 0

Testing: 1

Yielding: 1

Yielding: 2

Yielding: 3

Yielding: 4

Yielding: 1

Yielding: -2

  

 

 

itertools.groupby(iterable[, key])

返回一個產生按照key進行分組後的值集合的迭代器.

如果iterable在多次連續迭代中生成了同一項,則會定義一個組,如果將此函式應用一個分類列表,那麼分組將定義該列表中的所有唯一項,key(如果已提供)是一個函式,應用於每一項,如果此函式存在返回值,該值將用於後續項而不是該項本身進行比較,此函式返回的迭代器生成元素(key, group),其中key是分組的鍵值,group是迭代器,生成組成該組的所有項。

即:按照keyfunc函式對序列每個元素執行後的結果分組(每個分組是一個迭代器), 返回這些分組的迭代器

等價於

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

class groupby(object):

    # [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

    def __init__(self, iterable, key=None):

        if key is None:

            key = lambda x: x

        self.keyfunc = key

        self.it = iter(iterable)

        self.tgtkey = self.currkey = self.currvalue = object()

    def __iter__(self):

        return self

    def next(self):

        while self.currkey == self.tgtkey:

            self.currvalue = next(self.it)    # Exit on StopIteration

            self.currkey = self.keyfunc(self.currvalue)

        self.tgtkey = self.currkey

        return (self.currkey, self._grouper(self.tgtkey))

    def _grouper(self, tgtkey):

        while self.currkey == tgtkey:

            yield self.currvalue

            self.currvalue = next(self.it)    # Exit on StopIteration

            self.currkey = self.keyfunc(self.currvalue)

  

 

應用

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

from itertools import groupby

qs = [{'date' 1},{'date' 2}]

[(name, list(group)) for name, group in itertools.groupby(qs, lambda p:p['date'])]

  

 

Out[77]: [(1, [{'date'1}]), (2, [{'date'2}])]

 

 

>>> from itertools import *

>>> a = ['aa''ab''abc''bcd''abcde']

>>> for i, k in groupby(a, len):

...     print i, list(k)

...

2 ['aa''ab']

3 ['abc''bcd']

5 ['abcde']

  

 

 

另一個例子

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

from itertools import *

from operator import itemgetter

  

 

= dict(a=1, b=2, c=1, d=2, e=1, f=2, g=3)

di = sorted(d.iteritems(), key=itemgetter(1))

for k, g in groupby(di, key=itemgetter(1)):

    print k, map(itemgetter(0), g)

 

 

1 ['a''c''e']

2 ['b''d''f']

3 ['g']

  

 

 

itertools.ifilter(predicate, iterable)

返回的是迭代器類似於針對列表的內建函式 filter() , 它只包括當測試函式返回true時的項. 它不同於 dropwhile()

建立一個迭代器,僅生成iterable中predicate(item)為True的項,如果predicate為None,將返回iterable中所有計算為True的項

對函式func執行返回真的元素的迭代器

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

def ifilter(predicate, iterable):

    # ifilter(lambda x: x%2, range(10)) --> 1 3 5 7 9

    if predicate is None:

        predicate = bool

    for in iterable:

        if predicate(x):

            yield x

  

 

使用

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

from itertools import *

  

 

def check_item(x):

    print 'Testing:', x

    return (x<1)

 

for in ifilter(check_item, [ -1012341-2 ]):

    print 'Yielding:', i

 

Testing: -1

Yielding: -1

Testing: 0

Yielding: 0

Testing: 1

Testing: 2

Testing: 3

Testing: 4

Testing: 1

Testing: -2

Yielding: -2

  

 

 

itertools.ifilterfalse(predicate, iterable)

和ifilter(函式相反 , 返回一個包含那些測試函式返回false的項的迭代器)

建立一個迭代器,僅生成iterable中predicate(item)為False的項,如果predicate為None,則返回iterable中所有計算為False的項 對函式func執行返回假的元素的迭代器

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

def ifilterfalse(predicate, iterable):

    # ifilterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8

    if predicate is None:

        predicate = bool

    for in iterable:

        if not predicate(x):

            yield x

  

 

使用

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

from itertools import *

  

 

def check_item(x):

    print 'Testing:', x

    return (x<1)

 

for in ifilterfalse(check_item, [ -1012341-2 ]):

    print 'Yielding:', i

 

Testing: -1

Testing: 0

Testing: 1

Yielding: 1

Testing: 2

Yielding: 2

Testing: 3

Yielding: 3

Testing: 4

Yielding: 4

Testing: 1

Yielding: 1

Testing: -2

  

 

itertools.islice(iterable, stop)

itertools.islice(iterable, start, stop[, step])

返回的迭代器是返回了輸入迭代器根據索引來選取的項

建立一個迭代器,生成項的方式類似於切片返回值: iterable[start : stop : step],將跳過前start個項,迭代在stop所指定的位置停止,step指定用於跳過項的步幅。 與切片不同,負值不會用於任何start,stop和step, 如果省略了start,迭代將從0開始,如果省略了step,步幅將採用1.

返回序列seq的從start開始到stop結束的步長為step的元素的迭代器

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

def islice(iterable, *args):

    # islice('ABCDEFG', 2) --> A B

    # islice('ABCDEFG', 2, 4) --> C D

    # islice('ABCDEFG', 2, None) --> C D E F G

    # islice('ABCDEFG', 0, None, 2) --> A C E G

    = slice(*args)

    it = iter(xrange(s.start or 0, s.stop or sys.maxint, s.step or 1))

    nexti = next(it)

    for i, element in enumerate(iterable):

        if == nexti:

            yield element

            nexti = next(it)

  

 

使用

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

from itertools import *

  

 

print 'Stop at 5:'

for in islice(count(), 5):

    print i

 

print 'Start at 5, Stop at 10:'

for in islice(count(), 510):

    print i

 

print 'By tens to 100:'

for in islice(count(), 010010):

    print i

 

Stop at 5:

0

1

2

3

4

Start at 5, Stop at 10:

5

6

7

8

9

By tens to 100:

0

10

20

30

40

50

60

70

80

90

  

 

itertools.imap(function, *iterables)

建立一個迭代器,生成項function(i1, i2, ..., iN),其中i1,i2...iN分別來自迭代器iter1,iter2 ... iterN,如果function為None,則返回(i1, i2, ..., iN)形式的元組,只要提供的一個迭代器不再生成值,迭代就會停止。

即:返回一個迭代器, 它是呼叫了一個其值在輸入迭代器上的函式, 返回結果. 它類似於內建函式 map() , 只是前者在任意輸入迭代器結束後就停止(而不是插入None值來補全所有的輸入).

返回序列每個元素被func執行後返回值的序列的迭代器

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

9

10

def imap(function, *iterables):

    # imap(pow, (2,3,10), (5,2,3)) --> 32 9 1000

    iterables = map(iter, iterables)

    while True:

        args = [next(it) for it in iterables]

        if function is None:

            yield tuple(args)

        else:

            yield function(*args)

  

 

使用

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

from itertools import *

  

 

print 'Doubles:'

for in imap(lambda x:2*x, xrange(5)):

    print i

 

print 'Multiples:'

for in imap(lambda x,y:(x, y, x*y), xrange(5), xrange(5,10)):

    print '%d * %d = %d' % i

 

Doubles:

0

2

4

6

8

Multiples:

0 * 5 = 0

1 * 6 = 6

2 * 7 = 14

3 * 8 = 24

4 * 9 = 36

  

 

 

itertools.starmap(function, iterable)

建立一個迭代器,生成值func(*item),其中item來自iterable,只有當iterable生成的項適用於這種呼叫函式的方式時,此函式才有效。

對序列seq的每個元素作為func的引數列表執行, 返回執行結果的迭代器

複製程式碼程式碼如下:

1

2

3

4

def starmap(function, iterable):

    # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000

    for args in iterable:

        yield function(*args)

  


使用

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

from itertools import *

  

 

values = [(05), (16), (27), (38), (49)]

for in starmap(lambda x,y:(x, y, x*y), values):

    print '%d * %d = %d' % i

 

0 * 5 = 0

1 * 6 = 6

2 * 7 = 14

3 * 8 = 24

4 * 9 = 36

  

 

 

itertools.tee(iterable[, n=2])

返回一些基於單個原始輸入的獨立迭代器(預設為2). 它和Unix上的tee工具有點語義相似, 也就是說它們都重複讀取輸入裝置中的值並將值寫入到一個命名檔案和標準輸出中

從iterable建立n個獨立的迭代器,建立的迭代器以n元組的形式返回,n的預設值為2,此函式適用於任何可迭代的物件,但是,為了克隆原始迭代器,生成的項會被快取,並在所有新建立的迭代器中使用,一定要注意,不要在呼叫tee()之後使用原始迭代器iterable,否則快取機制可能無法正確工作。

把一個迭代器分為n個迭代器, 返回一個元組.預設是兩個

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

def tee(iterable, n=2):

    it = iter(iterable)

    deques = [collections.deque() for in range(n)]

    def gen(mydeque):

        while True:

            if not mydeque:             # when the local deque is empty

                newval = next(it)       # fetch a new value and

                for in deques:        # load it to all the deques

                    d.append(newval)

            yield mydeque.popleft()

    return tuple(gen(d) for in deques)

  

 

使用

複製程式碼程式碼如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

from itertools import *

  

 

= islice(count(), 5)

i1, i2 = tee(r)

 

for in i1:

    print 'i1:', i

for in i2:

    print 'i2:', i

 

i1: 0

i1: 1

i1: 2

i1: 3

i1: 4

i2: 0

i2: 1

i2: 2

i2: 3

i2: 4

  

 

itertools.takewhile(predicate, iterable)

和dropwhile相反

建立一個迭代器,生成iterable中predicate(item)為True的項,只要predicate計算為False,迭代就會立即停止。

即:從序列的頭開始, 直到執行函式func失敗.

複製程式碼程式碼如下:

1

2

3

4

5

6

7

def takewhile(predicate, iterable):

    # takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4

    for in iterable:

        if predicate(x):

            yield x

        else:

            break

  

 

使用

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

from itertools import *

  

 

def should_take(x):

    print 'Testing:', x

    return (x<2)

 

for in takewhile(should_take, [ -1012341-2 ]):

    print 'Yielding:', i

 

Testing: -1

Yielding: -1

Testing: 0

Yielding: 0

Testing: 1

Yielding: 1

Testing: 2

  

 

 

itertools.izip(*iterables)

返回一個合併了多個迭代器為一個元組的迭代器. 它類似於內建函式zip(), 只是它返回的是一個迭代器而不是一個列表

建立一個迭代器,生成元組(i1, i2, ... iN),其中i1,i2 ... iN 分別來自迭代器iter1,iter2 ... iterN,只要提供的某個迭代器不再生成值,迭代就會停止,此函式生成的值與內建的zip()函式相同。

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

9

izip(iter1, iter2, ... iterN):

返回:(it1[0],it2 [0], it3[0], ..), (it1[1], it2[1], it3[1], ..)...

  

 

def izip(*iterables):

    # izip('ABCD', 'xy') --> Ax By

    iterators = map(iter, iterables)

    while iterators:

        yield tuple(map(next, iterators))

  

 

 

使用

複製程式碼程式碼如下:

1

2

3

4

5

6

7

8

from itertools import *

  

 

for in izip([123], ['a''b''c']):

    print i

(1'a')

(2'b')

(3'c')

  

 


itertools.izip_longest(*iterables[, fillvalue])

 

與izip()相同,但是迭代過程會持續到所有輸入迭代變數iter1,iter2等都耗盡為止,如果沒有使用fillvalue關鍵字引數指定不同的值,則使用None來填充已經使用的迭代變數的值。

 

複製程式碼程式碼如下:

1