zoukankan      html  css  js  c++  java
  • ~~函数基础(七):生成器&迭代器~~

    进击のpython

    *****

    生成器


    上来说个这,就有点抽象了!

    我们先整点活儿

    宁,准备好了吗?

    直接相位猛冲!


    • 列表生成器

      需求来了,老弟!我有一个数组

      a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
      

      我想把列表里每个元素加一,怎么办呢?

      a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
      b = []
      for i in a:
          b.append(i+1)
      
      print()
      
      b
      

      还有吗?

      a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
      
      for index, i in enumerate(a):
          a[index] += 1
      print(a)
      

      还有吗?

      a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
      
      a = list(map(lambda x:x+1,a))
      print(a)
      

      还有吗?

      a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
      
      a = [i + 1 for i in a]
      print(a)
      

      最后一种的方式就是列表生成式(是不是很像三目运算??)


    • 生成器

      生成器,比如说我要是输出1~100

      怎么输出呢?

      for i in range(1,101):
          print(i)
      

      这大家都知道(不知道的滚回去看基础知识去,别在这捣乱)

      那有没有想过,range(1,100) 是什么呢?

      在py2.x系统下,我们可以看出来

      range(1,101)实际上是生成了一个从1~100的数字的列表

      那我要是有个这种句子呢?

      for i in range(1, 101):
          if i < 20:
              print(i)
      

      可以看出来我只需要20个数字,但是range给我生成了一个带有很多元素的列表

      即使里面大部分我都用不上,但是还是生成了。(while也行,别在这艮)

      那就会出现一个浪费空间的问题

      那我就要想了,能不能先生成一个我先用着,然后用完了再传下一个

      这个东西 就是 生成器

      做呢?有两种方式!


      将列表推导式的中括号变成小括号

      f = (x + 1 for x in range(10))
      
      print(f)                        # <generator object <genexpr> at 0x05681EF0>
      

      只是生成了生成规则,还没有产生数值

      那我要怎么产生数值呢?

      利用函数next()

      f = (x + 1 for x in range(10))
      
      print(next(f)) # 1
      print(next(f)) # 2
      print(next(f)) # 3
      print(next(f)) # 4
      print(next(f)) # 5 
      print(next(f)) # 6
      

      如果值取完了就会报错:

      要是想再使用这个生成器,那你就需要重新调用


      用循环来取

      这样就不会报错,会把值全都取出来

      f = (x + 1 for x in range(10))
      
      for i in f:
          print(i)
      

    • 函数生成器

      在做函数生成器之前,我们先试试输出100以内的斐波那契数列

      # 1 1 2 3 5 8 13 ... ...
      
      li = [1, 1]
      
      for i in range(2, 101):
          if li[i - 2] + li[i - 1] < 101:
              li.append(li[i - 2] + li[i - 1])
          else:
              break
      print(li)
      

      或者也可以这么写:

      # 0 1 1 2 3 5 8 13 ... ...
      
      a = 0
      b = 1
      count = 0
      while count < 20:
          tep = a
          a = b
          b = tep + b
          print(a,end=" ")
          count += 1
      

      那要是把这个东西改成函数怎么写??

      那很简单啊!

      # 0 1 1 2 3 5 8 13 ... ...
      
      def fib(n):
          a = 0
          b = 1
          count = 0
          while count < n:
              tep = a
              a = b
              b = tep + b
              print(a, end=" ")
              count += 1
      

      那函数生成器呢???更简单了

      看到print()没有?把 print()⇨ yield()

      大功告成!

      # 0 1 1 2 3 5 8 13 ... ...
      
      def fib(n):
          a = 0
          b = 1
          count = 0
          while count < n:
              tep = a
              a = b
              b = tep + b
              # print(a, end=" ")
              yield a
              count += 1
      
      
      print(fib(20))
      

      拿到了什么结果??(<generator object fib at 0x033A1EF0>)

      这是不是个生成器?(当然是!那么大个generator看不到啊)

      yield 暂停 你可以把它理解成 return 但是他后面的语句还是会执行的函数没有退出

      生成器是不是有 next() 函数啊,试试用 next() 打印这个结果

      有啥用???

      可太有用了!

      你没发现这个yield将函数进行中断操作了吗?

      什么意思呢?就是你可以执行着函数,然后停住他,执行点别的,再执行函数

      给你个例子,自己体会!

      # 0 1 1 2 3 5 8 13 ... ...
      
      def fib(n):
          a = 0
          b = 1
          count = 0
          while count < n:
              tep = a
              a = b
              b = tep + b
              # print(a, end=" ")
              yield a
              count += 1
      
      
      f = fib(20)
      print(next(f))
      print(next(f))
      print('-----"下面是上两个的和"-----')
      print(next(f))
      print(next(f))
      print(next(f))
      print(next(f))
      


    这个东西还是比较抽象的,但是很重要的熬,所以建议多练习

    自己试试输出一下斐波那契数列

    好好看看!很重要的!!!!!!!!!!!!!!


    迭代器


    回想一下啊,都有什么可以用for这个方法来循环呢?

    list tuple dict set str

    还有什么?

    嗯!上面写的生成器 genterator

    那就出来了┗|`O′|┛ 嗷~~

    我们把这些可以用for方法循环的对象称为可迭代对象 iterable

    这个词的意思就是可以遍历,可以循环的

    # 西瓜:三天之后,大家就知道什么是迭代了
    # 读者:A,他是别人的老师,现在又成了你的朋友。你给翻译翻译,什么叫迭代?翻译翻译,什么叫迭代?
    # A:这还用翻译,都说了。
    # 读者:我让你翻译给我听,什么叫迭代?
    # A:不用翻译,这就是迭代啊。
    # 西瓜:难道你听不懂什么叫迭代?
    # 读者:我就想让你翻译翻译,什么叫迭代!
    # A:迭代嘛
    # 读者:翻译出来给我听,什么他妈的叫迭代!什么他妈的叫他妈的迭代!
    # A:什么他妈的叫惊喜啊?
    # 西瓜:迭代就是可以用for方法循环的对象!明白了吗?
    # A:这就是迭代啊
    # 读者:翻译翻译 翻译翻译!
    # A:迭代就是可以用for方法循环的对象!
    # 读者:哈,大哥这他妈的就是迭代啊!小弟懂了
    # 西瓜:好
    

    可以被next()函数调用并不断返回下一个值的对象成为迭代器 :iterator

    而 生成器都可以迭代,而且还有next()方法

    所以生成器就可以约等于迭代器


    *真的重要*
    *必须康康*
  • 相关阅读:
    创建Variant数组
    ASP与存储过程(Stored Procedures)
    FileSystemObject对象成员概要
    Kotlin 朱涛9 委托 代理 懒加载 Delegate
    Kotlin 朱涛 思维4 空安全思维 平台类型 非空断言
    Kotlin 朱涛7 高阶函数 函数类型 Lambda SAM
    Kotlin 朱涛16 协程 生命周期 Job 结构化并发
    Proxy 代理模式 动态代理 cglib MD
    RxJava 设计理念 观察者模式 Observable lambdas MD
    动态图片 Movie androidgifdrawable GifView
  • 原文地址:https://www.cnblogs.com/jevious/p/11142896.html
Copyright © 2011-2022 走看看