python08-迭代器与生成器

Posted liangjiongyao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python08-迭代器与生成器相关的知识,希望对你有一定的参考价值。

一、什么是迭代器

  首先回顾一下,什么是递归?

    在调用一个函数的过程中,直接或间接地调用了函数本身这个就叫递归。

    举个问路的例子,你问张三火炉山在哪里?张三不知道,他说我帮你去问李四,李四对张三说我也不知道,你等着,我帮你去问王五。于是李四就去问王五,王五告诉李四    火炉山在xxx,李四就屁颠屁颠地跑回去告诉张三,张三知道答案后就告诉你,前面就是火炉山!

 

  什么是迭代?

    迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值

    举个造人的例子,你爷爷跟你奶奶生了你爸爸,你爸爸和你妈妈生了你,然后一代代这样繁衍下去....如果没有你爷爷奶奶,也就没有你爸爸,没有你爸爸也就没有你

 

  什么是迭代器?

    可以被next()函数调用并不断返回下一个值的对象称为迭代器,即迭代的工具

 

  什么是可迭代对象?

    实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)。一般把可以直接作用于for循环的对象统称为可迭代对象(Iterable),python内部的工具,如for循    环,sum,min,max,socket等都使用迭代器协议访问对象

    x=‘hello‘
    print(dir(x))
    iter_test=x.__iter__()

    print(iter_test)
    print(iter_test.__next__())
    print(iter_test.__next__())
    print(iter_test.__next__())
    print(iter_test.__next__())
    print(iter_test.__next__())
    print(iter_test.__next__())

 

  什么是迭代器协议?

    对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代(只能往后走不能往前退)

 

  字符串、列表、元组等为什么是可迭代对象?

    因为它们是可以被遍历的数据类型,也就是元素可以被一个一个取出来。

    s={1,2,3}
    for i in s: #只要能被for循环遍历的对象,都有__iter__()方法
        print(i)
    iter_s=s.__iter__()
    print(iter_s)
    print(iter_s.__next__())
    print(iter_s.__next__())
    print(iter_s.__next__())
    print(iter_s.__next__())

  

  迭代器与可迭代对象的区别?

    区别就是在迭代器里面有__next__方法,这也是它们之间的最根本区别。

    l=[1,2,3]
    iter_l=l.__iter__() #遵循迭代器协议,l是可迭代对象,iter_l是迭代器
    print(iter_l.__next__())
    print(iter_l.__next__())

 

  为什么要有for循环?

    因为字典、集合、文件对象这种数据类型是没有下标的,并且是无序的。若想取出其内部包含的元素,则必须找出一种不依赖于索引的方式,所以就需要有for循环。

    l=[1,2,3]
    index=0
    while index < len(l): # 不用下标索引遍历列表中的元素
        print(l[index])
        index+=1

 

    dic={‘a‘:1,‘b‘:2} #for循环为什么遍历的是字典的key?全是因为迭代协议中的next方法返回的值
    iter_d=dic.__iter__()
    print(iter_d.__next__())

    f=open(‘test.txt‘,‘r+‘)
    iter_f=f.__iter__()
    print(iter_f)
    print(iter_f.__next__(),end=‘‘)
    print(iter_f.__next__(),end=‘‘)

 

  for循环的工作原理

    字符串、列表、元组、字典、集合、文件对象这些都是可迭代对象,for循环在遍历他们的时候,其实首先调用了它们内部的iter方法,

    把他们变成一个可迭代对象,然后再调用可迭代对象的next方法取值,捕捉到StopIteration异常,就终止迭代。

    l=[1,2,3,4,5]
    diedai_l=l.__iter__()
    while True:  #模拟for循环
        try:
            print(diedai_l.__next__())
        except StopIteration:
            print(‘迭代完毕了,循环终止了‘)
            break

 

  迭代器的优缺点

    #优点:
      - 提供一种统一的、不依赖于索引的迭代方式
      - 惰性计算,节省内存
    #缺点:
      - 无法获取长度(只有在next完毕才知道到底有几个值)
      -一次性的,只能往后走,不能往前退

 

二、生成器

  什么是生成器?

    只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码。可以理解为一种数据类型,这种数据类型自动实现了迭代器协议,所    以生成器就是可迭代对象。

    def test():
        yield 1 #帮你返回值,并把你变成生成器
        yield 2
        yield 3
    g=test()
    print(‘来自函数‘,g) #<generator object func at 0x0000000002184360>
    print(g.__next__())
    print(g.__next__()) 

  表现形式

    函数式

      函数内部包含有yield关键字,使用yield语句返回结果,而不是return,yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执      行

      def test():
          yield 1 #帮你返回值,并把你变成生成器


      g=test()
      print(‘来自函数‘,g) #<generator object func at 0x0000000002184360>

 

    表达式 

      首先认识一下三元表达式:

      name=‘智障‘
      name=‘小鲜肉‘
      res=‘SB‘ if name == ‘智障‘ else ‘帅哥‘
      print(res) #返回SB

      所谓三元就是if name == ‘智障‘、else ‘帅哥‘、‘SB‘      

 

      再来认识一下列表解释:

      egg_list=[]
      for i in range(10):
          egg_list.append(‘鸡蛋%s‘ %i)
      print(egg_list)

      l=[‘鸡蛋%s‘ %i for i in range(10)]
      l1=[‘鸡蛋%s‘ %i for i in range(10) if i > 5 ] #可以,三元
      # l1=[‘鸡蛋%s‘ %i for i in range(10) if i > 5 else i] #没有四元表达式
      l2=[‘鸡蛋%s‘ %i for i in range(10) if i < 5]
      l3=[‘鸡蛋%s‘ %i for i in range(10) else ‘haha‘]  #报错,没有else

      print(l)
      print(l1)
      print(l2)

      

      最后就是生成器表达式:

      类似于列表解释,但是生成器表达式返回一个按需产生结果的一个对象,而不是一次构建一个结果列表,比列表解释节省内存

      laomuji=(‘鸡蛋%s‘ %i for i in range(10)) #生成器表达式
      print(laomuji)
      print(laomuji.__next__())
      print(laomuji.__next__())
      print(next(laomuji))
      print(next(laomuji))
      print(next(laomuji))
      print(next(laomuji))
      print(next(laomuji))
      print(next(laomuji))
      print(next(laomuji))
      print(next(laomuji))

 

  yield

      1、把函数做成迭代器
      2、对比return,可以返回多次值,可以挂起/保存函数的运行状态

 

  生成器的好处

      使用生成器会产生延迟操作,所谓延迟操作是指在需要的时候才产生结果,而不是立即产生结果,这也是生成器的主要好处

 





















































































以上是关于python08-迭代器与生成器的主要内容,如果未能解决你的问题,请参考以下文章

Python3 迭代器与生成器

python3 迭代器与生成器

Python的迭代器与生成器

Lesson 023 —— python 迭代器与生成器

python014 Python3 迭代器与生成器

Python迭代器与生成器