• Python-迭代协议-__iter__ __next__ iter next yield


    iter

      本质是for循环调用的实质,for循环通过调用这个函数返回可迭代对象生成器形式,开始迭代取值捕获StopIteration错误退出循环

      for循环首先找__iter__方法,然后再找 __getitem__方法,如果都没找到则报错,对象不是可迭代对象

    __iter__

      如果是自定义类生成的对象则iter方法调用__iter__函数, 这个函数必须返回迭代器对象

    next

      启动生成器。并获取生成器第一个值

    __next__

      将对象变成生成器对象,也是 next方法调用对象中__next__方法

    from random import randint
    
    
    class BeiMenChuiXue:
        """自己实现的迭代器"""
        def __init__(self, iterable):
            self.iterable = iterable
    
        def __next__(self):
            for member in self.iterable:
                yield member
    
    
    class DuGuJiuJiu:
        """可迭代对象"""
        def __init__(self, numbers):
            self.numbers = numbers
    
        def __iter__(self):
            # 通过全局函数 iter实现
            # return iter(self.numbers)
    
            # 交给自己实现的迭代器
            return next(BeiMenChuiXue(self.numbers))
    
    
    if __name__ == '__main__':
        numbers = [randint(-10, 10) for _ in range(10)]
        print(numbers)
        du_gu_jiu_jiu = DuGuJiuJiu(numbers)
        for member in du_gu_jiu_jiu:
            print(member)
    

      

     北门吹雪: https://www.cnblogs.com/2bjiujiu/

    yield

      yield可以跳出函数并传出一个值,也可以传递进去一个值被函数内部收到并接着执行函数,类似函数与函数之间形成通信并且可以暂停并启动函数的特性,是协程实现的最底层原理

    def bei_men_chui_xue():
        hai = yield "我是 bei_men_chui_xue 函数"
        print(hai)
    
    
    if __name__ == '__main__':
        bei = bei_men_chui_xue()
        message = bei.send(None)
        print(message)
        try:
            bei.send("我是 main 函数")
        except StopIteration as e:
            pass
    

      

    经验:

      1. for循环迭代的本质还是生成器对象,然后捕获StopIteration自动退出循环

      2. 协程实现的底层原理是yield特性,既可以暂停函数并传出一个值也可以接收一个值重新启动函数的特性最具有Python语言风格

      3. 迭代结束会自动触发StopIteration,这个异常是结束信号,需要捕获这个异常

    bei_men_chui_xue: https://www.cnblogs.com/2bjiujiu/

    通过yield读取大文件思路:

      1. 打开文件获得句柄 open

      2. 通过read方法读取指定偏移量数据

      3. 定义一个读生成器,传递文件句柄和读取偏移量

      4. 定义一个buf,循环判断分隔符是否在buf中,取出分隔符前面的字符(通过切片),yield出去,更新buf分隔符后面的字符

      5. 如果没有找到分隔符,则read数据,判断是否读取完毕,读取完毕退出,有数据则拼接到buf中

    def read_big_file(filename, read_size=20, sep='
    '):
        """读取大文件"""
        f = open(filename, 'r', encoding='utf-8')
        buf = ''
        sep_len = len(sep)
        while True:
            # 第一层取数据
            data = f.read(read_size)
            # 判断文件是否读完
            if data is None:
                raise StopIteration
            buf += data
            while True:
                # 第二层生成数据
                if sep in buf:
                    index = buf.index(sep)
                    yield buf[:index]
                    buf = buf[index + sep_len:]
                else:
                    break
    
    
    if __name__ == '__main__':
        file_name = "python_this.txt"
        read_generator = read_big_file(filename=file_name)
        oneline = next(read_generator)
        twoline = next(read_generator)
        threeline = next(read_generator)
        print(oneline, end='')
        print(twoline, end='')
        print(threeline, end='')
    

      

  • 相关阅读:
    java project 和 java web project 获取路径问题
    java.lang.UnsupportedClassVersionError: *** : Unsupported major.minor version 51.0
    Hibernate Annotation (Hibernate 注解)
    远程访问(post 传参数) 以及IOUtils复制文件
    使用jdk中keytool生成证书
    Chrome 的滚动条修改.
    https原理及tomcat配置https方法
    HttpClient 访问 https 出现peer can't
    Dom4j解析xml
    Tomcat Server 配置
  • 原文地址:https://www.cnblogs.com/2bjiujiu/p/9143737.html
Copyright © 2020-2023  润新知