Python常用内建模块-itertools

1. itertools模块介绍

itertools是Python中的一个内置模块,在Python中提供了很多方便快捷的迭代器函数,能够高效地进行迭代操作,对于需要将复杂的迭代操作简单化的开发者非常有用。该模块包括三类函数:

返回可迭代对象的函数

返回迭代器的函数

返回迭代器生成器的函数

1.1 返回可迭代对象的函数

itertools模块中有许多返回可迭代对象的函数,下面我们分别介绍几个常用的函数:

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

该方法可以创建一个无限的计数器迭代器,从start开始,以step为步长进行计数。

import itertools

counter = itertools.count()

data = [next(counter) for _ in range(5)]

print(data)

输出结果:[0, 1, 2, 3, 4]

当然,我们也可以通过设置start参数进行指定起始值。

import itertools

counter = itertools.count(start=5)

data = [next(counter) for _ in range(5)]

print(data)

输出结果:[5, 6, 7, 8, 9]

我们还可以通过设置step参数进行指定步长。

import itertools

counter = itertools.count(start=0, step=2)

data = [next(counter) for _ in range(5)]

print(data)

输出结果:[0, 2, 4, 6, 8]

1.1.2 itertools.cycle(iterable)

该函数可以对原有数据进行循环迭代,当原数据迭代完成后,会不断重复迭代。

import itertools

counter = itertools.cycle(['A', 'B', 'C'])

data = [next(counter) for _ in range(5)]

print(data)

输出结果:['A', 'B', 'C', 'A', 'B']

1.1.3 itertools.repeat(object, times=None)

该函数可以将一个元素重复迭代指定的次数,如果不指定次数,则会无限地重复迭代。

import itertools

data = [i for i in itertools.repeat(10, 5)]

print(data)

输出结果:[10, 10, 10, 10, 10]

1.2 返回迭代器的函数

接着我们来介绍几个返回迭代器的函数:

1.2.1 itertools.compress(data, selectors)

该函数可以根据selectors的真假值对data进行过滤。

import itertools

data = ['A', 'B', 'C', 'D']

selectors = [True, False, True, False]

filtered_data = itertools.compress(data, selectors)

print(list(filtered_data))

输出结果:['A', 'C']

1.2.2 itertools.dropwhile(predicate, iterable)

该函数会跳过原数据中所有符合条件的元素,直到遇到第一个不符合条件的元素,之后返回剩余部分的迭代器。

import itertools

data = [1, 3, 5, 2, 4, 6]

filtered_data = itertools.dropwhile(lambda x: x<5, data)

print(list(filtered_data))

输出结果:[5, 2, 4, 6]

1.2.3 itertools.takewhile(predicate, iterable)

该函数只返回符合条件的元素,直到遇到第一个不符合条件的元素时就立即停止迭代。

import itertools

data = [1, 3, 5, 2, 4, 6]

filtered_data = itertools.takewhile(lambda x: x<5, data)

print(list(filtered_data))

输出结果:[1, 3]

1.3 返回迭代器生成器的函数

最后我们来介绍几个返回迭代器生成器的函数:

1.3.1 itertools.chain(*iterables)

该函数可以将多个可迭代对象拼接到一起,返回一个生成器,生成器会依次迭代每一个可迭代对象中的元素。

import itertools

data = itertools.chain([1, 2, 3], [4, 5, 6])

print(list(data))

输出结果:[1, 2, 3, 4, 5, 6]

1.3.2 itertools.dropwhile(predicate, iterable)

该函数可以对一个可迭代对象进行分组,分组方式由key函数指定。

import itertools

data = [{'name': 'Tom', 'age':20},

{'name': 'Jack', 'age':18},

{'name': 'Lucy', 'age':22},

{'name': 'Lily', 'age':18}]

grouped_data = itertools.groupby(data, key=lambda x:x['age'])

for key, group in grouped_data:

print(key, list(group))

输出结果:

20 [{'name': 'Tom', 'age': 20}]

18 [{'name': 'Jack', 'age': 18}, {'name': 'Lily', 'age': 18}]

22 [{'name': 'Lucy', 'age': 22}]

2. itertools源码解析

在介绍完itertools的常用函数后,我们来深入学习一下itertools的源码实现。itertools的源码在Python的官方库中是可以查看的,也可以在网上找到。

2.1 itertools.count源码解析

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

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

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

it = _countiter(start, step)

return it

class _countiter:

def __init__(self, value, step):

self.value = value

self.step = step

def __iter__(self):

return self

def __next__(self):

result = self.value

self.value += self.step

return result

从源码中可以看出,count函数会返回一个_countiter的实例,而_countiter是一个迭代器,其__next__方法会不断返回value,并将value加上step。

2.2 itertools.cycle源码解析

def cycle(iterable):

# cycle('ABCD') --> A B C D A B C D A B C D ...

saved = []

for element in iterable:

yield element

saved.append(element)

while saved:

for element in saved:

yield element

从源码中可以看出,cycle函数返回一个生成器,其yield关键字前后轮流返回输入的可迭代对象的元素,当迭代器迭代完所有元素后,会无限重复地返回原队列的所有元素。

2.3 itertools.repeat源码解析

def repeat(object, times=None):

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

if times is None:

while True:

yield object

else:

for i in range(times):

yield object

从源码中可以看出,repeat函数返回一个生成器,当times为None时,它会不断重复yield object,当times不为None时,它会重复yield object次数为times。

2.4 itertools.chain源码解析

def chain(*iterables):

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

for it in iterables:

for element in it:

yield element

从源码中可以看出,chain函数返回一个生成器,它会首先迭代第一个可迭代对象中的所有元素,然后迭代第二个,第三个,直到最后一个可迭代对象中的所有元素。

2.5 itertools.groupby源码解析

def groupby(iterable, key=None):

# groupby('AAAABBBCCDAABBB') -> A B C D A B

# groupby('ABBCcAD', lambda x: x.upper()) -> A B C A D

if key is None:

key = lambda x: x

it = iter(iterable)

try:

first = next(it)

except StopIteration:

return

groupkey = key(first)

group = [first]

for item in it:

itemkey = key(item)

if itemkey != groupkey:

yield (groupkey, group)

groupkey = itemkey

group = [item]

else:

group.append(item)

yield (groupkey, group)

从源码中可以看出,groupby函数返回一个生成器,它会先迭代一次可迭代对象,并将第一个元素的key值保存起来,然后循环迭代所有元素,当元素的key值与前一个元素的key值不同时,就会生成前一个分组的(groupkey, group)二元组,并将groupkey设置为当前元素的key值,将group保存为新的列表。

3. 总结

itertools模块是Python常用的标准库之一,它提供了非常强大而又方便快捷的迭代函数。通过本文的介绍,我们了解了itertools的一些常用函数,并深入源码解析了其中几个函数的实现原理。学习完本文后,读者可以更加熟练地使用itertools模块对数据进行处理,也可以更深入地理解Python中的迭代机制。

后端开发标签