可迭代对象和迭代器

python 从可迭代对象获得迭代器
迭代器实现了 __next__ __iter__ 两个方法
没有实现 __iter__ 无法用 for 迭代
迭代器是这样一个对象,实现了无参数的 next 方法,返回序列中的下一个元素;如果没有元素了,那么抛出 StopIteration 异常。

  1. import re
  2. import reprlib
  3. RE_WORD = re.compile('\w+')
  4. class Sentence:
  5. # 可迭代对象
  6. def __init__(self, text):
  7. self.text = text
  8. self.words = RE_WORD.findall(text)
  9. def __repr__(self):
  10. return 'Sentence(%s)' % reprlib.repr(self.text)
  11. def __iter__(self):
  12. # 实现了该方法就是可迭代对象
  13. # 可迭代对象,返回迭代器,每次实例化后返回新的迭代器
  14. # 调用 iter(x) 判断x 是否是可迭代对象
  15. return SentenceIterator(self.words)
  16. class SentenceIterator:
  17. # 迭代器
  18. def __init__(self, words):
  19. self.words = words
  20. self.index = 0
  21. def __next__(self):
  22. # 返回单个元素
  23. # 迭代器必须实现的方法
  24. try:
  25. word = self.words[self.index]
  26. except IndexError:
  27. raise StopIteration()
  28. self.index += 1
  29. return word
  30. def __iter__(self):
  31. # 迭代器必须实现的方法
  32. # 返回自身
  33. 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’):
    1. process_line(line)

迭代读取文件,直到遇到空行或者文件末尾停止

  1. <a name="yfEs7"></a>
  2. ### 生成器
  3. 只要定义了yield 的函数就是一个生成器函数<br />惰性获取数据
  4. <a name="DJZJg"></a>
  5. #### 2.1生成器应用,读取大数据文件
  6. ```python
  7. # 正常csv文件可能是单个分隔符(,),现在分隔符是两个字符(||),Python无法处理这种两个字符的分隔符
  8. # 需要自定义读取一行数据,split(分隔符), 返回格式化数据
  9. def read_file_head(file, delimiter=None):
  10. # 读取文件头 head
  11. # 自定义分割符,(,;||等)
  12. with open(file) as f:
  13. one_line = f.readline()
  14. return one_line.strip().split(delimiter)
  15. def delimited(file, delimiter='\n', bufsize=4096):
  16. # 一次读取文件4096字节数据,如果出现一行结尾,则yield 这行数据
  17. buf = ''
  18. while True:
  19. newbuf = file.read(bufsize)
  20. if not newbuf:
  21. yield buf
  22. return
  23. buf += newbuf
  24. lines = buf.split(delimiter)
  25. for line in lines[:-1]:
  26. yield line
  27. buf = lines[-1]
  28. def read_file_by_line(file, lf, length, flag):
  29. """
  30. file 文件名
  31. lf 文件一行末尾数据格式(换行符)
  32. length 默认一行数据长度
  33. flag 一行字段与字段之间分隔符
  34. """
  35. head = read_file_head(file, flag)
  36. with open(file, encoding='utf-8') as f:
  37. next(f) # 迭代第一行,这是文件头
  38. lines = delimited(f, lf, 4096)
  39. for line in lines:
  40. res = dict(zip(head, line.split(flag)))
  41. if len(res) == length:
  42. yield res

2.2用作协程