返回顶部

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)

  

输出结果如下

 

posted @ 2018-12-10 15:52  Crazymagic  阅读(314)  评论(0编辑  收藏  举报