前面五小节讲述的是iterator的基本特性以及一些常用技巧:
4.1 manually consuming a iterator--next方法
4.2 delegeting iteration--定义__iter__方法
4.3 Creating New Iteration Patterns With Generators--yield
4.4 Implementing the Iterator Protocal--yield from
4.5 Iterating In Reverse--定义__reversed__方法
4.6. Defining Generator Functions with Extra State
problem
你想要将从外部获取的信息以iterator的形式展示
solution
定义class并搭配iter方法是解决这类问题的首选
1 | from collections import deque |
以上代码将test.txt读入并初始化一个linehistory对象,查找该文件中是否包含python字符串,若包含则输出该字符串以及其所在的行号。
discussion
在需要对迭代对象进行复杂的处理逻辑或是与其他对象进行交互时,上述方法应该是首选的iteration方案。但有个潜在缺点是不能对实例化的对象直接进行next操作,而需要先使用iter()函数进行处理再调用next方法
1 | next(lines)#error |
4.7. Taking a Slice of an Iterator
problem
你想要给某个iterator进行像list那样的切片操作,但是iterator对象原生是不支持slice操作的。
solution
itertools中有个islice方法正式为满足此类需求而产生的。
1 | def Count(n): |
discussion
itertools中的islice可以像切片操作一样返回特定迭代次数之间的数据,但应该强调的是,这个操作的机制是使用iterator并将切片起点次数之前的值舍弃,一直迭代获取到切片结束为止。这会改变被操作的iterator对象。因此,如果想要保留iterator中的值,那还是应该先将其转化为list在进行切片操作。
4.8. Skipping the First Part of an Iterable
problem
你想要在某个循环的过程中跳过某几行,比如文件开头几行的注释说明。
solution
当然啦,则个问题用上面的itertools.islice也是可以解决的。但是我们想要更优雅的方式,怎么办呢,itertools提供了dropwhile函数,可以跳过某些元素。
1 | from itertools import dropwhile |
如果不使用dropwhile的话,可能会出现这样的代码:
1 | with open('test.txt') as f: |
如果使用表达式进行筛选,那可能会把所有注释都删掉,显然这不是我们想要的:
1 | with open('test.txt') as f: |
permutation还可以接受一个额外的参数用来控制每种排列中元素的个数。
1 | from itertools import combinations |
如果想要获得元素可重复的组合结果,可以使用combinations_with_replacement
1 | from itertools import combinations_with_replacement |
solution
这一小节只是展示了itertools中的一部分功能,当你遇到需要对多个元素排列组合的情况时,可以使用这些库函数而不需要自己动手。
4.10. Iterating Over the Index-Value Pairs of a Sequence
problem
你想在迭代一个iterator对象的同时记录输出元素的位置信息。
solution
The built-in enumerate() function handles this quite nicely:
1 | items=['a','b','c'] |
enumerate默认是从0开始对下表进行计数,也可以传入一个参数作为开始的值,如上面例子中使用了1作为开始基数。
这个方法可以非常方便的对一个文件内容进行逐行的分析并保存结果,比如统计文件中各个单词的出现的行数。
1 | words_summary=defaultdict(list) |
经过上述代码处理后,会得到以单词名称为键名,已列表为键值的字典,列表中保存的是对应单词在文本中出现的行数。
discussion
enumerate返回的仍然是iterator对象,但是这个iterator对象在迭代过程中返回的值是一个个tuple,由索引和值组成。
在使用enumerate时,应该注意,在for循环中要保留处理对象的格式,比如
1 | items=[('a','b'),('c','d'),('e','f')] |