def__iter__(self): for lineno, line inenumerate(self.lines, 1): self.history.append((lineno, line)) yield line
defclear(self): self.history.clear()
withopen('somefile.txt') as f: lines = linehistory(f) for line in lines: # 最后一句触发if if'python'in line: for lineno, hline in lines.history: print('{}:{}'.format(lineno, hline), end='')
# somefile.txt内容如下: # hello world # this is a test # of iterating over lines with a history # python is fun
# 打印如下: # 2:this is a test # 3:of iterating over lines with a history # 4:python is fun
4.7 迭代器切片
函数 itertools.islice() 适用于在迭代器和生成器上做切片操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import itertools
defcount(n): whileTrue: yield n n += 1
c = count(0)
for x in itertools.islice(c,10,15): print(x) # 10 # 11 # 12 # 13 # 14
withopen('myfile.txt', 'r') as f: lines = f.readlines()
for idx, line inenumerate(lines): # Create a list of words in current line words = [w.strip().lower() for w in line.split()] for word in words: word_summary[word].append(idx)
import os import fnmatch import gzip import bz2 import re
defgen_find(filepat, top): ''' Find all filenames in a directory tree that match a shell wildcard pattern ''' for path, dirlist, filelist in os.walk(top): for name in fnmatch.filter(filelist, filepat): yield os.path.join(path, name)
defgen_opener(filenames): ''' Open a sequence of filenames one at a time producing a file object. The file is closed immediately when proceeding to the next iteration. ''' for filename in filenames: if filename.endswith('.gz'): f = gzip.open(filename, 'rt') elif filename.endswith('.bz2'): f = bz2.open(filename, 'rt') else: f = open(filename, 'rt') yield f f.close()
defgen_concatenate(iterators): ''' Chain a sequence of iterators together into a single sequence. ''' for it in iterators: yieldfrom it
defgen_grep(pattern, lines): ''' Look for a regex pattern in a sequence of lines ''' pat = re.compile(pattern) for line in lines: if pat.search(line): yield line
if __name__ == '__main__':
# Example 1 lognames = gen_find('access-log*', 'www') files = gen_opener(lognames) lines = gen_concatenate(files) pylines = gen_grep('(?i)python', lines) for line in pylines: print(line)
# Example 2 lognames = gen_find('access-log*', 'www') files = gen_opener(lognames) lines = gen_concatenate(files) pylines = gen_grep('(?i)python', lines) bytecolumn = (line.rsplit(None,1)[1] for line in pylines) bytes = (int(x) for x in bytecolumn if x != '-') print('Total', sum(bytes))
4.14 展开嵌套的序列
使用yield和yield from
1 2 3 4 5 6 7 8 9 10 11 12
from collections.abc import Iterable
defflatten(alist): for ele in alist: ifisinstance(ele,Iterable): yieldfrom flatten(ele) else: yield ele
defflatten(items, ignore_types=(str, bytes)): for x in items: ifisinstance(x, Iterable) andnotisinstance(x, ignore_types): for i in flatten(x): yield i else: yield x
对比:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
from collections.abc import Iterable
defflatten(alist): res = [] for ele in alist: ifisinstance(ele,Iterable): res.extend(flatten(ele)) else: res.append(ele) return res