08 python迭代器和生成器
python中的迭代协议
什么是迭代器?
迭代器是访问集合内部元素的一种方式,一般用于遍历数据
迭代器和用下标的访问方式不一样,也就是说迭代器是不能返回数据的,迭代器提供了一种惰性方式产生数据
可迭代实质上是由__iter__来实现的
迭代器必须要同时有__iter__和__next__魔法函数
from collections.abc import Iterable, Iterator a = [1, 2] print(isinstance(a, Iterable)) print(isinstance(a, Iterator))
输出结果如下
什么是迭代器和可迭代对象
可迭代对象 内部实现了 __iter__方法 可以用于遍历
迭代器 内部实现了 __iter__和__next__方法 可以用于遍历和next()取值
把一个可迭代对象编程迭代器,可以使用iter(可迭代对象)
a = [1, 2] iter_rator = iter(a)
自定义一个迭代器
class MyIterator: def __init__(self, employee_list): self.iter_list = employee_list self.index = 0 def __iter__(self): return self def __next__(self): #真正返回迭代值的逻辑 try: word = self.iter_list[self.index] except IndexError: raise StopIteration self.index += 1 return word if __name__ == "__main__": company = MyIterator(["tom", "bob", "jane"]) print(next(company)) for item in company: print (item)
输出结果如下
生成器函数的使用
生成器函数,函数里只要有yield关键字
#生成器函数,函数里只要有yield关键字 def gen_func(): yield 1 yield 2 yield 3 gen = gen_func() print(next(gen)) for item in gen: print(item)
输出结果如下
递归实现 斐波那契求值
def fib(index): if index <= 2: return 1 else: return fib(index-1) + fib(index-2) if __name__ == '__main__': print(fib(8))
输出结果如下
生成器实现斐波那契
def gen_fib(index): n,a,b = 0,0,1 while n<index: yield b a,b = b, a+b n += 1 if __name__ == '__main__': gen_fib = gen_fib(10) for value in gen_fib: print(value)
打印结果如下
生成器在UserList中的应用
查看UserList的源码
from collections import UserList
可以看到每次遍历的时候都会通过yield返回一个值
生成器如何读取大文件
假如有一个500G的文件,我们想要读取它,如果它是一行一行的话我们可以使用for循环一行一行的读
这里的一个500G的文件是在一行,这时候我们可以用生成器来读取
input.text
Prior to beginning tutoring sessions{|}, I ask new students to fill{|} out a brief self-assessment{|} where they rate their{|} understanding of various Python concepts. Some topics ("control flow with if/else" or "defining and using functions") are understood by a majority of students before ever beginning tutoring. There are a handful of topics, however, that almost all{|} students report having no knowledge or very limited understanding of. Of these
生成器读取大文件
#500G, 特殊 一行 def myreadlines(f, newline): buf = "" # 缓存,用来保存生成器一次返回的数据 while True: while newline in buf: pos = buf.index(newline) yield buf[:pos] buf = buf[pos + len(newline):] # 获取的是满足条件的一行+ {|}后面的内容 chunk = f.read(4096) if not chunk: #说明已经读到了文件结尾 yield buf break buf += chunk with open("input.txt") as f: for line in myreadlines(f, "{|}"): print (line)
输出结果如下