可迭代对象和迭代器
python 从可迭代对象获得迭代器
迭代器实现了 __next__ __iter__ 两个方法
没有实现 __iter__ 无法用 for 迭代
迭代器是这样一个对象,实现了无参数的 next 方法,返回序列中的下一个元素;如果没有元素了,那么抛出 StopIteration 异常。
import reimport reprlibRE_WORD = re.compile('\w+')class Sentence:# 可迭代对象def __init__(self, text):self.text = textself.words = RE_WORD.findall(text)def __repr__(self):return 'Sentence(%s)' % reprlib.repr(self.text)def __iter__(self):# 实现了该方法就是可迭代对象# 可迭代对象,返回迭代器,每次实例化后返回新的迭代器# 调用 iter(x) 判断x 是否是可迭代对象return SentenceIterator(self.words)class SentenceIterator:# 迭代器def __init__(self, words):self.words = wordsself.index = 0def __next__(self):# 返回单个元素# 迭代器必须实现的方法try:word = self.words[self.index]except IndexError:raise StopIteration()self.index += 1return worddef __iter__(self):# 迭代器必须实现的方法# 返回自身return self
迭代器与可迭代对象总结
- 可迭代对象返回迭代器(iter)
- 可迭代对象无法通过next 方法,获取下个数据
- 迭代器无法获取集合中的某个值,只能依次访问
- 不能回退,支持对聚合对象的多种遍历
- 要知道,可迭代的对象有个 iter 方法,每次都实例化一个新的迭代器;而迭代器要实现 next 方法,返回单个元素,此外还要实现 iter 方法,返回迭代器本身。
iter 鲜为人知的用法
iter(func, i) i 为一种标识,当到i,抛出异常 ```python with open(path, ‘r’) as f: for line in iter(f.readline, ‘\n’):process_line(line)
迭代读取文件,直到遇到空行或者文件末尾停止
<a name="yfEs7"></a>### 生成器只要定义了yield 的函数就是一个生成器函数<br />惰性获取数据<a name="DJZJg"></a>#### 2.1生成器应用,读取大数据文件```python# 正常csv文件可能是单个分隔符(,),现在分隔符是两个字符(||),Python无法处理这种两个字符的分隔符# 需要自定义读取一行数据,split(分隔符), 返回格式化数据def read_file_head(file, delimiter=None):# 读取文件头 head# 自定义分割符,(,;||等)with open(file) as f:one_line = f.readline()return one_line.strip().split(delimiter)def delimited(file, delimiter='\n', bufsize=4096):# 一次读取文件4096字节数据,如果出现一行结尾,则yield 这行数据buf = ''while True:newbuf = file.read(bufsize)if not newbuf:yield bufreturnbuf += newbuflines = buf.split(delimiter)for line in lines[:-1]:yield linebuf = lines[-1]def read_file_by_line(file, lf, length, flag):"""file 文件名lf 文件一行末尾数据格式(换行符)length 默认一行数据长度flag 一行字段与字段之间分隔符"""head = read_file_head(file, flag)with open(file, encoding='utf-8') as f:next(f) # 迭代第一行,这是文件头lines = delimited(f, lf, 4096)for line in lines:res = dict(zip(head, line.split(flag)))if len(res) == length:yield res
