[6]迭代器和生成器

  • 迭代器为集合提供了一种访问元素的方式,用来遍历元素
  • 迭代器遍历与下标访问不一样,下标访问是返回一个数值,迭代器不返回任何数值,迭代器能够惰性获取元素

迭代协议

  • 实现__iter__魔法函数,对象是可迭代的
  • 实现__next__、__iter__ ,对象是一个迭代器

自定义迭代器

#自定义迭代器
class MyIter:
    def __init__(self, list):
        self.index = 0 #内部维护的指针
        self.list = list #需要迭代的对象

    #每次进行迭代操作,都会调用一次next魔法函数,返回一个结果
    def __next__(self):
        try:
            item = self.list[self.index]
        except IndexError: #当访问列表超出范围时,会抛出IndexError 异常
            raise StopIteration #抛出异常结束迭代
        self.index += 1 #内部指针加一
        return item #返回迭代的结果


class Color:
    def __init__(self,*args):
        self.items = list(args)

    def __iter__(self): #当使用 for,iter 对实例进行操作时候,返回一个迭代对象
        return MyIter(self.items)

    def __getitem__(self, item): # 当没有实现iter时,会进行降级操作,创建一个默认迭代器
        return self.items[item]


c = Color('red', 'blue', 'write', 'green', 'yellow', 'pink')

t = iter(c) # 会调用对象的 iter魔法函数,返回一个迭代器

for i in c: # 会调用对象的 iter魔法函数,返回一个迭代器,一直调用迭代器的 next魔法函数,直到抛出 StopIteration异常
    print(i)

生成器的使用

# 斐波那契数列 1、1、2、3、5、8、13、21、34


def fid(index):
    """
    返回第 index 位的数值
    """
    if index <= 2:
        return 1
    else:
        return fid(index-1) + fid(index-2)


def fid2(index):
    """
    返回列表表现形式
    """
    n, a, b = 1, 1, 1
    l = [1]
    while n < index:
        l.append(b)
        a, b = b, a+b
        n += 1
    return l


def fid3(index):
    """
    使用生成器器实现
    """
    n, a, b = 1, 1, 1
    yield 1
    while n < index:
        yield b
        a, b = b, a+b
        n += 1


if __name__ == "__main__":
    # 直接调用会返回生成器,而不是数值
    f = fid3(5)
    print(f)

    for i in fid3(2):
        print(i)

生成器与函数调用的区别是

  • 函数的代码块会完整的执行一遍,遇到return返回结果。下次在调用函数时会重新从代码块的第一行执行。
  • 生成器调用时,遇到yield会暂停代码块的执行,返回结果。下次调用生成器,会在上次yield停止的地方继续往下执行。

生成器应用

使用迭代器,读取一个以 | 分割的大文件

import os

def get():
    fd = os.open('test.log', os.O_RDONLY)

    str_buf = ''
    while True:
        data = os.read(fd, 33)
        if data == bytes('','utf8'):
            break
        str_buf += str(data, 'utf8')

        if '|' in str_buf:
            while True:
                index = str_buf.find('|')
                yield str_buf[:index+1]
                str_buf = str_buf[index+1:]
                if "|" not in str_buf:
                    break


if __name__ == '__main__':
    for item in get():
        print(item)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值