本文始发于我的公众号:TechFlow,原创不易,求个关注程序员
今天是Python专题的第8篇文章。web
今天咱们依然介绍的是迭代器,不过介绍的是几个比较经常使用的高级用法,在实际场景当中很是实用,能够帮助咱们大大简化代码的复杂度。数组
首先是跳过开始部分,这个在咱们读取文本的时候最经常使用。在实际的应用当中,好比记录的日志或者是代码等等,通常来讲头部都会附上一段说明,或者用注释标注或者是用特殊的符号标记。这些信息是给用到数据的程序员看的,当咱们经过代码获取数据的时候,显然是但愿能够过滤掉这些信息的。编辑器
好比咱们有一段数据,它的开头用#作了一些注释:函数
# This is a data for student
# Rows 100
xiaoming, 17, 99;
xiaoli, 18, 98;
...
复制代码
常规操做当中,咱们会建立一个打开文件的迭代器,咱们经过遍历这个迭代器去获取文件当中的数据:工具
with open('xxxx.txt') as f:
for line in f:
print(line)
复制代码
若是只是用来输出还好,若是咱们须要加工文件当中的数据,那么头部的注释信息就会干扰咱们代码的运行。咱们固然能够手动加入一些判断,可是这会比较麻烦,代码也不够美观。针对这个问题,一个比较好的解决方案是dropwhile。this
dropwhile是itemtools当中的一个函数,它能够接收一个咱们自定义的过滤函数和迭代器从新生成一个新的迭代器,这个新的迭代器当中会过滤掉以前迭代器头部不符合咱们要求的数据:spa
在刚才的例子当中咱们想要过滤掉头部加了#注释的部分,咱们能够这么操做:日志
from itertools import dropwhile
with open('xxxx.txt') as f:
for line in dropwhile(lambda line: line.startswith('#'), f):
print(line)
复制代码
这样出来的结果就没有头部咱们不须要的内容了。code
当咱们知道头部不符合状况的数据的格式的时候,可使用dropwhile来规定过滤的格式。若是咱们知道须要过滤的条数,则可使用另一个工具,叫作islice,它的本质是一个切片函数,就像是Python当中数组的切片功能同样,能够切出迭代器当中指定片断的数据。
举个例子:
from itertools import dropwhile
with open('xxxx.txt') as f:
for line in islice(f, 3, None):
print(line)
复制代码
这样咱们就会从第三行开始获取,以前的数据会被过滤掉。它其实就表明着数组当中[3: ]的切片操做。
咱们都知道在C++当中有一个叫作next_permutation的函数,能够传入一个数组,返回下一个字典序的排列。在Python当中也有一样的功能,可是是以迭代器的形式使用的。
举个简单的例子,好比咱们有a, b, c三个元素,咱们但愿求出它的全部排列:
items = ['a', 'b', 'c']
from itertools import permutations
for p in permutations(items):
print(p)
复制代码
permutations还支持多传一个参数,好比上述的排列当中咱们但愿只保留前两个元素,除了切片以外,咱们只须要多传一个参数就行了,like this:
for p in permutations(items, 2):
print(p)
复制代码
除了排列以外,itertools当中还支持组合,用法仍是同样,只是把函数名称换成是combinations而已:
from itertools import combindations
for c in combinations(items):
print(c)
复制代码
在通常的组合当中,一个元素一旦被选中那么它接下来就会从候选集当中移除,不再会被选中。若是咱们但愿得到有放回的组合,咱们能够再换一个函数,这个函数名称有点长,可是名字倒也直观叫作combinations_with_replacement。但既然是有放回的抽样,咱们须要设定元素的数量,不然抽样能够无限进行下去。
for c in combinations_with_replacement(items, 3):
print(c)
复制代码
上一篇文章当中咱们介绍了zip能够同时迭代多个迭代器,除此以外还有一种状况是咱们须要把多个迭代器串起来迭代。好比系统的日志打在了多个文件当中,咱们但愿找出其中有error的日志来分析。这个时候,咱们但愿的不是同时读取多个迭代器,而是但愿可以有办法将多个迭代器的内容串联起来。这个功能就是itertools当中的chain方法,它接受多个迭代器,当咱们遍历的时候,会自动将多个迭代器的内容串联起来,咱们能够无缝迭代。
举个例子:
from itertools import chain
nums = [1, 2, 3]
chars = ['a', 'b', 'c']
for i in chain(nums, chars):
print(i)
复制代码
这样咱们会把nums和chars当中的内容一块儿输出出来,就好像从头至尾只执行了一个迭代器同样。
你可能会说咱们不用chain也能够实现啊,咱们能够这样:
for i in nums + chars:
print(i)
复制代码
的确,从结果上来看这样也是行得通的。可是若是咱们分析一下内部执行的时候的中间变量,会发现当咱们执行nums+chars的时候,其实是先建立了一个新的临时list。而后在这个list当中存储nums和chars的数据,也就是说咱们迭代的实际上是这个新的list。这带来的结果是咱们额外开辟了一段内存,而且花费了一些时间。若是咱们使用chain,它并不会有这样的中间变量,彻底是经过迭代器来执行的迭代,很是节省内存,这也是chain的优势。
对于归并操做咱们应该都不陌生,在以前的归并排序以及一些题解的文章当中咱们见过不少次。一样,咱们在使用工具合并多个迭代器内容的时候,若是迭代器当中的内容有序,咱们也能够对多个迭代器当中的元素进行归并,而再也不须要咱们本身手动操做。
使用咱们以前介绍的heapq的库能够很是轻松地作到这一点,咱们一块儿来看一个例子:
a = [1, 3, 5]
b = [2, 4, 6]
import heapq
for c in heapq.merge(a, b):
print(c)
复制代码
执行以后,咱们会获得[1, 2, 3, 4, 5, 6]的结果。也就是说经过heapq.merge操做,咱们把多个有序的迭代器合并到了一块儿。固然咱们也能够本身合并,但若是咱们只是须要利用当中的数据的话,使用merge操做能够节省内存空间。
到这里内容就结束了,本文和以前的文章基本上列举完了经常使用的迭代器用法。固然,除了上述讲到的内容以外,Python当中的迭代器还有一些其余的用法,不过相对不太经常使用,感兴趣的同窗能够私下了解。
今天的文章就是这些,若是以为有所收获,请顺手点个关注或者转发吧,大家的举手之劳对我来讲很重要。