• python基础之三大器中迭代器和生成器


    迭代器

    • 迭代对象: 在python中,但凡内部含有iter方法的对象,都是可迭代对象

    • 迭代器: 在python中,内部含有__Iter__方法并且含有__next__方法的对象就是迭代器。

      可迭代对象 str list set dic

    • python中规定,只要具有__ iter__()方法就是可迭代对象

      str.__iter__()# list.__iter__()# tuple.__iter__()# dict.__iter__()# set.__iter__()
      
      • 将可迭代对象转换成迭代器

        lis = lst.__iter__()
        
        # print(lis.__next__())  # 下一位
        # print(lis.__next__())  # 下一位
        # print(lis.__next__())  # 下一位
        # print(lis.__next__())  # 下一位
        有多少元素就能next 多少次 超过范围报错
        
        文件句柄就是一个迭代器 # f = open("usrinfo","a",encoding="utf-8")
        

        while模拟for的内部循环机制

        将可迭代对象转换成迭代器,然后利用next进行取值,最后利用异常处理处理StopIteration抛出的异常。

        s = "alex"
        s1 = s.__iter__()
        while True:
            try: # 尝试着运行一下缩进体中的代码
                print(s1.__next__())
            except StopIteration:
                break
        

      可迭代对象如何转化成迭代器,并且取值

      方法一:

      lst = [1,2,3,4]
      l = lst.__iter__()
      print(1.__next__())  #1
      print(1.__next__())  #2
      print(1.__next__())  #3
      print(1.__next__())  #4
      方法二
      lst = [1,2,3,4]
      l = iter(lst)
      print(next(l))  #1
      print(next(l))  #2
      print(next(l))  #3
      print(next(l))  #4   #推荐
      

      python2 和python3

      py2没有__iter__()  有iter()
      py3 有__iter__()  有iter()
      

      可迭代对象优点和缺点:

      #优点
        1.使用灵活(每个可迭代对象都有自己的方法)
        2.能够直接查看元素的个数
      #缺点
        占内存
      应用:内存空间大,当数据量比较少,建议使用可迭代对象
      

      迭代器的优缺点及应用

      #具有__iter__()和__next__()方法就是一个迭代器
      #优点
           节省内存
      #缺点
        1 只能向一个方向执行,不能退回
        2 一次性的
        3 不能灵活操作,不能直接看元素的个数
      应用:当你的数据量过大,大到足以撑爆你的内存或者你以节省内存为首选因素时,将数据集设置为迭代器是一个不错的选择。(可参考为什么python把文件句柄设置成迭 
      代器)。
      

    时间换空间:迭代器,生成器,用大量的时间来节省空间

    空间换时间:可迭代对象,用大量空间来节省时间

    lst = [1,2,3,4]
    l = iter(lst)
    #print(l) 输出结果是迭代器的内存地址 <list_iterator object at 0x0000018117F0BA58>
    for i in l:# for循环可以直接去循环迭代器 
    	print(i)
    
    迭代器也是一个可迭代对象

    生成器

    • 生成器的本质就是一个迭代器

    • 最大的区别:

      • 迭代器:文件句柄,通过数据转换 python自带提供
      • 生成器:程序员自己实现
    • 生成器的目的:不在通过数据转换实现,而是通过代码编写实现

    • 生成器的定义:

      1.基于函数实现的生成器

      2.表达式实现生成器

      这是一个函数
      def func():
      	print(1)
      	return 5
      print(func())  这是一个函数
      

      这是一个生成器

      def func():
      	print(1)		
      	yield 5
        print(func())    创建一个生成器对象  <generator object func at 0x0000025A8B022EB8>
      

      表达式形式的生成器

      gen = (i**2 for i in range(10))
      print(next(gen))  
      博客推导式那里细讲
      
      函数print(func()) 得到的是return返回的值,而生成器print(fun()) 得到的是生成器对象的内存地址
      补充运行代码情况
      # def func():
      #     print(foo)      报错
      # func()
      
      # def func():
      #     print(foo)    不报错     
      
      因为计算机在查看代码时候会进行  1 语法分析  2词法分析   第一个是语法没有错,foo没有定义,但是他调用了,语法分析时没有问题,但是执行调用使用词法分析就 
      会报错
      第二个虽然没定义foo  但是语法没有错误,词法错误,但是函数体没有调用,故不会报错
      

      生成器怎么用:

      特点:惰性机制

      yield 和 return部分功能很像

      • 版一
      def func( ):
        	yield 1       #记录执行位置的
        	yield 2
        	yield 3	
      g = func()     #获取的是生成器的内存地址
      print(next(g)) #1
      print(next(g)) #2
      print(next(g)) #3   惰性机制,不next 不往下执行
      
      • 版二
      def func():
      	yield 1
      	yield 2
          yield 3
      g =func()
      g1 =func()
      g2= func()
      print(g,g1,g2)   输出三个<generator object func at 0x00000133E5DA7990>  只不过后边的地址不一样,说明创建了三个生成器 
      
      def func():  
        	yield
          print(func().__next__())    NONE   #得到是yield 返回的NONE
      
      def func():   
      	yield [1,2,3,4,5]
        	print(func().__next__(),type(func().__next__()))
      	得到的是[1,2,3,4,5]  类型是List
      
      def func():      !!!!!这个有意思  结果是 1 NONE  <class 'function'>
      	def foo():   
        	print(1)  
        yield foo
      g = func().__next__()
      print(g(),type(g)) 
      
      def func():   
        yield 1,2,3,4,5   
        print(123)    
        yield 111
      g = func()
      print(next(g))
      print(next(g))
      输出结果(1,2,3,4,5)  123  111      yield惰性 next往下走 
      
      yield from 
      
      def func():
      	yield [1,2,23,54,2]    #将列表整体返回 
      	yield from  [1,2,23,54,5]  #将列表中的元素逐个返回
      g = func()
      print(next(g)) [1,2,23,54,2]
      print(next(g))  1
      print(next(g))  2
      print(next(g))  23
      print(next(g))  54
      print(next(g))  5
      

      总结:

      在我理解就是生成器就是人造的迭代器,通过next取值,用时间换空间!

      生成器一定是一个迭代器,但是迭代器不一定是一个生成器

      怎么触发生成器
      遇见for 循环迭代时触发
      迭代器和生成器的优点:

      节省内存

      迭代器和生成器的缺点

      1.不能直接使用元素
      2.不能直观查看元素的个数
      3.使用不灵活
      4.稍微消耗时间
      5.一次性的,不能逆行
      

      当数据量特别大的时候,一定要记得用生成器

      区分迭代器和生成器:

      lst = [1,2,3]
      print(lst.__iter__())
      
      def func():
      	yield 1
      print(func())
      # 看内存地址   结果会显示iterator是迭代器  generator是生成器
      

      yeild

      return一般在函数中只设置一个,他的作用是终止函数,并且给函数的执行者返回值。

      yield在生成器函数中可设置多个,他并不会终止函数,next会获取对应yield生成的元素。

      • yield 能返回多个,以元组的形式储存

      • yield 能返回各种数据类型

      • yield 能写多个并且都执行

      • yield 能够记录执行位置

      • yield 后边不写内容,默认返回NONE

      • yield 都是将数据一次性返回

      • yield from 是将数据逐个返回

      可迭代对象:
      具有__iter__()方法的就是一个可迭代对象
      迭代器:
      具有__iter__()和__next__()方法就是一个迭代器
      生成器:
      基于函数创建的生成器,函数体中必须存在yield
      
  • 相关阅读:
    函数中的不定长参数研究 *and**
    copy()与直接=赋值的区别
    python的位运算符
    python的list相关知识
    hadoop报错:hdfs.DFSClient: Exception in createBlockOutputStream
    转载计算机的潜意识的文章:机器学习的入门级经典读物
    完全分布式hadoop2.5.0安装 VMware下虚拟机centos6.4安装1主两从hadoop
    PE结构总导航
    利用函数指针绕过断点
    为什么Fun函数能够执行
  • 原文地址:https://www.cnblogs.com/zzsy/p/12219533.html
Copyright © 2020-2023  润新知