Itertools简介
Itertools简介,Python为创建自定义迭代器提供了非常好用的模块——itertools。由itertools提供的工具通常都很快速而且节省内存。你可以利用这些组成部分去创建自己独有的迭代器以完成高效的循环。在本章节中,我们会对每个组成部分都进行举例说明,最后你可以在自己代码基础之上借助自己的理解去使用它们。
让我们先看一些不会终止的迭代器。
无限迭代器
Itertools包具有三个无限迭代器。当你使用它们的时候,你要知道何时去跳出这个循环,不然你将陷入无限循环之中。
在生产数字或者遍历事先不知道长度的数据时非常有用,现在开始学习一下这些有趣的迭代器吧!
Count(start=0,step=1)
Count迭代器会返回均匀间隔的值,以你传入的数字(即start参数)为起始点。Count也接受step参数。下面是个简单的例子:
>>>fromitertoolsimportcount
>>>foriincount(10):
...ifi>20:
...break
...else:
...print(i)
...
10
11
12
13
14
15
16
17
18
19
20
这里我们从itertools中引入了count并且创建了一个for循环。在循环中添加了一个检查语句,当循环超过20时跳出,否则就打印出当前产生的数字。你能发现输出的数字从10开始,那就是我们传给count的第一个参数即start参数。
另一种限制无限迭代输出的方法就是使用另一个Itertools的子模块,即islice。结果如下:
>>>fromitertoolsimportislice
>>>foriinislice(count(10),5):
...print(i)
...
10
11
12
13
14
这里我们引入了islice并且让count从10开始计数,5次后跳出循环。如同你猜想的那样,islice的第二个参数就意味着结束迭代。但是它并不是“当到达数字5时停止”的意思,而是指“当迭代5次后停止”。
Cycle(iterable)
Cycle迭代器允许你在一系列数据中无限循环。比如说传递一个包含三个字母的字符串,可以看下会发生什么:
>>>fromitertoolsimportcycle
>>>count=0
>>>foritemincycle('XYZ'):
...ifcount>7:
...break
...print(item)
...count+=1
...
X
Y
Z
X
Y
Z
X
Y
这里我们创建了一个for循环以在三个字母中无限循环。当然我们并不想永远地循环下去,所以加了一个简单的计数器以跳出循环。
你也可以使用Python内置的next去依次遍历由itertools产生的迭代器:
>>>polys=['triangle','square','pentagon','rectangle']
>>>iterator=cycle(polys)
>>>next(iterator)
'triangle'
>>>next(iterator)
'square'
>>>next(iterator)
'pentagon'
>>>next(iterator)
'rectangle'
>>>next(iterator)
'triangle'
>>>next(iterator)
'square'
在上述代码中,我们创建了一个简单的几何列表,并将它传递给了cycle,再将返回的结果保存到iterator变量中,然后借助于next函数,每次都能返回迭代器中的一个数据。由于这个迭代器是无限循环的,所以我们可以一直调用next,而且永远不会跳出。
Repeat(object[,times])
Repeat迭代器会无限的一次又一次地返回一个对象,除非你设置了times参数。它跟cycle很像,但是它并不是在一系列值上进行循环。可以看个简单的例子:
>>>fromitertoolsimportrepeat
>>>repeat(5,5)
repeat(5,5)
>>>iterator=repeat(5,5)
>>>next(iterator)
5
>>>next(iterator)
5
>>>next(iterator)
5
>>>next(iterator)
5
>>>next(iterator)
5
>>>next(iterator)
Traceback(mostrecentcalllast):
PythonShell,prompt21,line1
builtins.StopIteration:
这里我们引入了repeat,并且告诉它将数字5循环5次,然后我们对这个迭代器调用next函数六次以观察是否正常工作。当你执行这段代码的时候,你会发现程序抛出了StopIteration因为执行超过了迭代器的范围。
会终止的迭代器
你创建的大部分迭代器都是会终止的。在本段中,我们将开始学习Itertools中会终止的迭代器。为了获取可读的输出,我们将使用Python内置的list类型。如果你不使用list,那么你将得到一个Itertools对象。
Accumulate(iterable[,func])
Accumulate迭代器会返回累积后的结果或是你传递给acuumulate的函数计算后的累积结果。Acuumulate的默认操作就是加法,下面是个简单的例子:
>>fromitertoolsimportaccumulate
>>>list(accumulate(range(10)))
[0,1,3,6,10,15,21,28,36,45]
这里引入了accumulate,而且传递给一个0-9的列表。它会依次地累加,所以第一个值是0,第二个是0+1,第三个是1+2等。现在让我们引入operator模块,并且加入到accumulate中:
>>>importoperator
>>>list(accumulate(range(1,5),operator.mul))
[1,2,6,24]
这里我们传递了1-4的列表给accumulate迭代器,同时传递了一个函数operator.mul给它。这个函数会将参数进行乘法去处。所以对于每一次迭代,它都会用乘法代替加法(1×1=1,1×2=2,2×3=6等)。
Accumulate的文档中展示了一些其他有趣的例子比如货款的摊销或混乱的递推关系。你应该看下这些例子,它真的值得你花费时间去看。
Chain(*iterables)
Chain迭代器将接受一系列的可迭代对象并将其平铺成一个长的迭代对象。最近我正在做的项目中正好需要它的帮助。比如我们拥有了一个包含了一些数据的列表以及另两个想加入其中的列表,但是我们仅仅想加入每个列表中的元素,开始我是这么做的:
>>>my_list=['foo','bar']
>>>numbers=list(range(5))
>>>cmd=['ls','/some/dir']
>>>my_list.extend(cmd,numbers)
>>>my_list
['foo','bar',['ls','/some/dir'],[0,1,2,3,4]]
这并不是我预期得到的结果。Itertools模块提供了扩展列表的更优雅的方法,就是使用chain:
>>>fromitertoolsimportchain
>>>my_list=list(chain(['foo','bar'],cmd,numbers))
>>>my_list
['foo','bar','ls','/some/dir',0,1,2,3,4]
一些聪明的读者可能发现其实完全不用itertools也能完成这项工作,比如说这样:
>>>my_list=['foo','bar']
>>>my_list+=cmd+numbers
>>>my_list
['foo','bar','ls','/some/dir',0,1,2,3,4]
的确,两种方法都是可用的。在我知道chain之前或许我会用这个方法,但是我认为chain会更加的优雅和容易理解。
Chain.from_iterable(iterable)
你也可以使用chain中的方法from_iterable。这个方法会和直接使用chain有点区别。在这种方法中,你不能直接传递给一系列的可迭代对象,而是嵌套的列表:
>>>fromitertoolsimportchain
>>>numbers=list(range(5))
>>>cmd=['ls','/some/dir']
>>>chain.from_iterable(cmd,numbers)
Traceback(mostrecentcalllast):
PythonShell,prompt66,line1
builtins.TypeError:from_iterable()takesexactlyoneargument(2given)
>>>list(chain.from_iterable([cmd,numbers]))
['ls','/some/dir',0,1,2,3,4]
这里我们同样引入了itertools,然后尝试传递给它两个列表,但是却得到一个TypeError。为了修正这个问题,我们将cmd和numbers放入一个列表中并传递给from_iterable方法。这虽然有点轻微区别但是同样好用!
Compress(data,selectors)
Compress子模块接受两个参数,可以用第二个迭代对象去过滤第一个。通常第二个可迭代对象是一个Booleans类型的列表(或者是0,1)。下面是个例子:
>>>fromitertoolsimportcompress
>>>letters='ABCDEFG'
>>>bools=[True,False,True,True,False]
>>>list(compress(letters,bools))
['A','C','D']
在这个例子中,我们有七个字母和包含5个布尔值的列表。然后我们将其传递给compress函数。该函数会对每个数进行检查,如果第二个参数值是True,那么就会保留下第一个对象中的值。否则就会被删掉。因此观察上述例子,你会注意到我们只在1,3,4位置了使用了True,因而就对应着A,C,D。
Python培训、Python培训班、Python培训机构,就选光环大数据!
还不够过瘾?想学习更多?点击 http://hadoop.aura.cn/python/ 进行Python学习!
大数据培训、人工智能培训、Python培训、大数据培训机构、大数据培训班、数据分析培训、大数据可视化培训,就选光环大数据!光环大数据,聘请专业的大数据领域知名讲师,确保教学的整体质量与教学水准。讲师团及时掌握时代潮流技术,将前沿技能融入教学中,确保学生所学知识顺应时代所需。通过深入浅出、通俗易懂的教学方式,指导学生更快的掌握技能知识,成就上万个高薪就业学子。 更多问题咨询,欢迎点击------>>>>在线客服!