- Python进阶编程:编写更高效、优雅的Python代码
- 刘宇宙 谢东 刘艳
- 560字
- 2021-04-30 12:39:48
4.1.6 跳过可迭代对象的开始部分
在实际应用中,我们会有类似跳过可迭代对象的需求。
itertools模块中有一些函数可以实现这个需求,如itertools.dropwhile()函数。该函数需要传递一个函数对象和一个可迭代对象,返回一个迭代器对象,丢弃直到函数返回Flase之前的原有序列中的所有元素,然后返回后面的所有元素。
如读取一个开始部分是几行注释的源文件,代码如下:
with open('/etc/passwd') as f: for line in f: print(f'{line}', end='')
如跳过开始部分的注释行,代码如下:
from itertools import dropwhile with open('/etc/passwd') as f: for line in dropwhile(lambda line: line.startswith('#'), f): print(f'{line}', end='')
如果已经明确知道要跳过的元素的个数,可以使用itertools.islice()函数来代替上述代码,代码(iter_skip.py)示例如下:
from itertools import islice items = ['w', 'o', 'r', 12, 5, 7, 90] for x in islice(items, 3, None): print(x)
执行py文件,输出结果如下:
12 5 7 90
示例中,islice()函数最后的None参数指定了获取items中从第3个到最后的所有元素,如果None和3的位置对调,意思就是仅仅获取前3个元素(这与切片的相反操作[3:]和[:3]原理是一样的)。
dropwhile()和islice()是两个帮助函数,作用是避免写出类似如下的冗余代码:
with open('/etc/passwd') as f: # Skip over initial comments while True: line = next(f, '') if not line.startswith('#'): break # Process remaining lines while line: # Replace with useful processing print(line, end='') line = next(f, None)
跳过一个可迭代对象的开始部分与过滤是不同的。如上述代码的第一个部分可能会这样重写:
with open('/etc/passwd') as f: lines = (line for line in f if not line.startswith('#')) for line in lines: print(line, end='')
这样写确实可以跳过开始部分的注释行,但是同样会跳过文件中其他的注释行。
注意 这里的方案适用于所有可迭代对象,包括那些事先不能确定大小,如生成器、文件及其他类似的对象。