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取值,用时间换空间!

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

    迭代器和生成器的优点:

    节省内存

    迭代器和生成器的缺点

    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

相关推荐