zoukankan      html  css  js  c++  java
  • 函数【五】生成器/推导式

    py_生成器、列表推导式

     

    一、生成器

    1、什么是生成器?

      可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象;

    2、生成器在python中的表现形式?

    • 生成器函数:常规函数定义,但是使用yield语句而不是使用retum语句返回结果,yield语句一次返回一个结果,在每个结果中间挂机函数的状态,以便下次从他离开的地方执行;
    • 生成器表达式:类似于列表推导,但是生成器返回按需要产生结果的一个对象,而不是一次构建一个列表
      #生成器函数(只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码)
      cp = [1,2,3,4,5]
      def test():
          yield 1
          yield 2
          yield 3
      date = test()
      print(next(date))
      print(next(date))
      print(next(date))
      
      生成器函数
      生成器函数
      #三元表达式
      name = "lw"
      res = "sb" if name == "lw" else "帅哥"
      print(res)
      
      egg1 = ["鸡蛋 %s" %i for i in range(10) if i > 5 ]
      print(egg1)
      
      #正常列表(在内存中存储)
      egg_list = []
      for i in range(10):
          egg_list.append("鸡蛋 %s" %i)
      print(egg_list)
      
      #列表解析(在内存中存储)
      egg = ["鸡蛋 %s" %i for i in range(10)]
      print(egg)
      
      #生成器表达式(基于迭代器协议转换成可迭代对象,不占内存)
      laomuji = ("鸡蛋 %s" %i for i in range(10))
      print(laomuji)   #<generator object <genexpr> at 0x000001A6F46231A8>
      print(laomuji.__next__()) #等于next(laomuji)
      
      生成器表达式

      3、生成器取值的几种方式

      • 直接调用生成器内置的__next__方法;生成器内的数据取完,在取会抛出StopIteration
        def func():
            print(1)
            yield 5    # 我的函数走到这了
            print(2)
            yield 9    # 我的函数走到这了
        
        g = func()   # 生成一个生成器
        
        print(g.__next__())
        print(g.__next__())  # 每次取值会从上一个yield开始
        print(g.__next__())  # 生成器内的数据取完,在取会抛出StopIteration
        
        next方法
        next方法
        • 生成器调用send()方法,send()相当于(next + 传值),传值给yield,第一次调用生成器的时候使用send里边的值必须是None
          def func():
              print(1)
              a = yield 2    # 1.挂起 2.返回值 3.接受值
              print(a)
              print(3)
              b = yield 4
              print(b)
              c = yield 9
          g = func()  # 生成一个生成器
          print(g.__next__())
          print(g.send('123'))
          print(g.send('234'))
          #第一次调用生成器的时候使用send里边的值必须是None
          
          send方法

           4、简述yield与yield from的区别

          def generator():
              for i in range(5):
                  yield i
          t = generator()
          print(t.__next__())
          
          def generator_1():
              yield 1
              yield 2
              yield 3
              yield 4
              yield 5
          t1 = generator_1()
          print(t1.__next__())
          
          上面这两种方式是完全等价的,只不过前者更简单一些。
          
          yield
          yield
          def generator1():
              item = range(10)
              for i in item:
                  yield i
          
          def generator2():
              yield ‘a‘
              yield ‘b‘
              yield ‘c‘
              yield from generator1() #yield from iterable本质上等于 for item in iterable: yield item的缩写版
              yield from [11,22,33,44]
              yield from (12,23,34)
              yield from range(3)
          
          for i in generator2() :
              print(i)
          
          
          从上面的代码可以看书,yield from 后面可以跟的式子有“ 生成器  元组 列表等可迭代对象以及range()函数产生的序列”
          
          yield from
          yield from
          def test():
              for i in range(10):
                  yield i
          a = test()
          print(a.__next__())
          for j in a:
              print(j)
          
          def test():
              yield from range(10)
          b = test()
          print(b.__next__())
          for j in b:
              print(j)

          二、推导式

          # 推导式:
          # 1.列表
          # 2.集合
          # 3.字典
          # 4.生成器表达式(只要是小括号的就是生成器表达式)
          li = []
          for i in range(10):
              li.append(i)
          print(li)
          
          print([i for i in range(10)])
          [结果 语法] #容器
          
          li = []
          for i in range(10):
              if i%2 == 1:
                  li.append(i)
          print(li)
          
          print([i for i in range(10) if i%2 == 0])  # 过滤(筛选)
          
          li = []
          for i in range(10):
              for em in range(3):
                  li.append(em)
          print(li)
          
          print([j for i in range(10) for em in range(3) for j in range(5)])
          
          集合推导式
          s = {i for i in range(10)}
          print(s)
          
          字典推导式
          print({i:i+1 for i in range(10)})
          
          生成器表达式
          g = (i for i in range(10))

          总结:

              #     1.生成器的本质就是一个迭代器
          # 2.生成器一定是一个迭代器,迭代器不一定是一个生成器
          # 3.生成器是可以让程序员自己定义的一个迭代器
          # 4.生成器的好处,节省内存空间
          # 5.生成器的特性 一次性的,惰性机制,从上向下
          # 6.send相当于 next+传值,第一次触生成器的时候,如果使用send(None)值必须是None,一般我建议你们使用__next__
          # 7. python2 iter() next()
          # python3 iter() next() __next__() __iter__()
          # 8.yield from 将可迭代对象元素逐个返回
  • 相关阅读:
    学习之路 1-2
    学习之路 1-1
    【LifecycleException】: org.apache.catalina.LifecycleException: A child container failed during start 解决
    【JAVA】java中int转成String位数不足前面补零例如:1->001
    【Docker】 Error running deviceCreate (CreateSnapDeviceRaw)
    【java】解决java compiler level does not match the version of the installed java project facet
    【Mysql】SpringBoot阿里Druid数据源连接池配置
    【JVM】JVM优化过程全记录
    【JavaScript】windows.open用法详解
    【Java】JavaMail 554错误解决方法
  • 原文地址:https://www.cnblogs.com/youxiu123/p/11480659.html
Copyright © 2011-2022 走看看