20190220 可迭代对象、迭代器、生成器

可迭代对象、迭代器、生成器

说明

  • 可迭代对象包含迭代器。

  • 如果一个对象拥有__iter__方法,是可迭代对象(类似接口);如果一个对象拥有__next__方法,是迭代器(类似接口的实现类)。

  • 定义可迭代对象,必须实现__iter__方法;定义迭代器,必须实现__iter__和__next__方法。

  • 具有yield关键字的函数都是生成器

自定义一个迭代器


class MyIterable:



    def __iter__(self):

        return self



    def __init__(self, lst):

        self.lst = lst

        self.index = 0



    def __next__(self):

        try:

            ret = self.lst[self.index]

            self.index += 1

        except IndexError:

            raise StopIteration



        return ret





if __name__ == '__main__':

    li = MyIterable([1, 2, 3, 5])

    for i in li:

        print(i)

自定义一个生成器和一个普通函数的区别


# 一个普通的函数

def fun():

    return 1 # return关键字在这里只能定义一个





# 只要函数中有yield关键字就是生成器

def gen_fun():

    yield 1

    yield 2

    yield 3 # 但是yield和return不同可以定义多个





if __name__ == '__main__':

    # python编译字节码的时候,会根据yield关键字认定这个函数是生成器。

    # 然把这个函数转换成一个生成器,这个过程完全是python帮助我们进行的。

    gen = gen_fun() # <generator object gen_fun at 0x03C7DC30>

    ret = fun() # 1



    # gen_fun()执行,返回了生成器对象

    # fun()执行,返回了1



    # 遍历生成器

    for v in gen:

        print(v) # 1 2 3

使用生成器写一个斐波那契额数列函数


# 使用生成器技术写一个斐波那契数列函数

def gen_fib(index):

    n, a, b = 0, 0, 1



    while index > n:

        yield b

        a, b = b, a + b

        n += 1





if __name__ == '__main__':

    for i in gen_fib(1000000): # 每一位的数据都是动态生成的,非常节省内存资源

        print(i)

使用生成器读写大文件


def read_file(fp, spl_str):

    """

    读取大文件

    :param fp: 文件读写句柄

    :param spl_str: 每一行的分隔符

    """

    str_buf = ''

    spl_len = len(spl_str)



    while 1:

        # 缓存中找分隔符

        while spl_str in str_buf:

            # 找到分隔符位置,用来切片字符串

            index = str_buf.index(spl_str)

            # yield出切片后的字符串

            yield str_buf[:index]

            # 将分隔符后面的有效字符串缓存

            str_buf = str_buf[index + spl_len:]



        # 读取信息

        chunk = fp.read(4096 * 10)

        # 处理读到数据

        if chunk:

            str_buf += chunk

        # 处理剩余数据

        else:

            yield str_buf

            break





if __name__ == '__main__':

    with open('data', 'r') as file:

        for con in read_file(file, '{|}'):

            print(con)

posted @ 2019-04-13 02:04  耿文浩  阅读(127)  评论(0编辑  收藏  举报