zoukankan      html  css  js  c++  java
  • python学习之路---day12

                   生成器和生成器表达式
    一:生成器
    生成器实质上就是迭代器。
      三种方式获取生成器:
        01:通过生成器函数
        02:通过各种推导式实现生成器
        03:通过数据的转换也可以获取生成器
    eg:普通函数
        def fun()
            print("111")
            return
         ret=func()
         print(ret)
         结果:
         111
         222
     将函数的return  换成yield  就是生成器
         def fun()
            print("111")
            yield
         ret=func()
         print(ret)
         结果:<generator object func at 0x10567ff68>
         打印结果:结果是一个函数名字的内存地址
    原因:由于函数中存在了yield. 那么这个函数就是⼀个⽣成器
                函数. 这个时候. 我们再执⾏这个函数的时候. 就不再是函数的执⾏了.
                ⽽是获取这个⽣成器.如何使⽤呢? 想想迭代器. ⽣成器的本质是迭代器.
                所以. 我们可以直接执⾏__next__()来执⾏
         其实return和yield一样都有返回值,return返回值后,就退出函数,后面的函数就不在执行
         yield 则是在返回  返回值后 ,还给上一个yield 的变量赋值 
    案例结果说明
    例如:
             def eat():
                 print("我吃什么啊")
                 a = yield "馒头"
                 print("a=",a)
                 b = yield "⼤饼"
                 print("b=",b)
                 c = yield "⾲菜盒⼦"
                 print("c=",c)
                 yield "GAME OVER"
            gen = eat() # 获取⽣成器
            ret1 = gen.__next__()
            print(ret1)
            ret2 = gen.send("胡辣汤")
            print(ret2)
            ret3 = gen.send("狗粮")
            print(ret3)
            ret4 = gen.send("猫粮")
            print(ret4)
    
            打印结果:send和__next__()区别:
                1. send和next()都是让⽣成器向下走⼀次
                2. send可以给上⼀个yield的位置传递值, 不能给最后⼀个yield发送值.
                   在第⼀次执⾏⽣
                   成器代码的时候不能使⽤send()
    案例解释
    二:生成器的作用:
    生成器可以用for循环来循环获取内部的元素:
    def func():
                 print(111)
                 yield 222
                 print(333)
                 yield 444
                 print(555)
                 yield 666
            gen = func()  #这里并没有直接执行这个函数,只是获取了这个函数生成器,
            for i in gen:  #在循环这个函数后,生成器才会执行func()这个函数。i才会找gen要值,func才会执行
            print(i)
            结果:
            111
            222
            333
            444
            555
            666
    
    
    

    三:列表推导式:
      例如:
        lst = []
        for i in range(1, 15):
            lst.append(i)
        print(lst)
        这个代码块是,给出一个列表,通过循环,将数字添加到新的列表中去
        001):可以用列表推导式:
         lst = [i for i in range(1, 15)]
            print(lst)
            列表是常用写法:
            [ 结果 for 变量 in 可迭代对象]
        002):列表推导式还可以用来筛选
            获取1-100内所有的偶数
            lst = [i for i in range(1, 100) if i % 2 == 0]
            print(lst)

    四:生成器和列表推导式的区别:
      生成器: 有yield的函数体
        列表推导式:(  [ 结果 for 变量 in 可迭代对象] )
        列表推导式是通过一行来构建我们需要的列表,列表推导式看起来代码简单。但是出了
        错误很难排查!
    五:生成器表达式:
    001):⽣成器表达式和列表推导式的语法基本上是⼀样的. 只是把[]替换成()
          
    gen = (i for i in range(10))
                print(gen)
                结果:
                <generator object <genexpr> at 0x106768f10>
    
                    打印的结果就是⼀个⽣成器. 我们可以使⽤for循环来循环这个⽣成器:
                gen = ("麻花藤我第%s次爱你" % i for i in range(10))
                for i in gen:
                 print(i)
    View Code
    六:⽣成器表达式和列表推导式的区别:
      1. 列表推导式比较耗内存. ⼀次性加载. ⽣成器表达式⼏乎不占⽤内存. 使⽤的时候才分
          配和使⽤内存
        2. 得到的值不⼀样. 列表推导式得到的是⼀个列表. ⽣成器表达式获取的是⼀个⽣成器.

        举个栗⼦.

        
    同样⼀篮⼦鸡蛋. 列表推导式: 直接拿到⼀篮⼦鸡蛋. ⽣成器表达式: 拿到⼀个老⺟鸡. 需要
        鸡蛋就给你下鸡蛋.
        ⽣成器的惰性机制: ⽣成器只有在访问的时候才取值. 说⽩了. 你找他要他才给你值. 不找他
        要. 他是不会执⾏的.
    View Code
    七:总结: 推导式有, 列表推导式, 字典推导式, 集合推导式, 没有元组推导式
       ⽣成器表达式: (结果 for 变量 in 可迭代对象 if 条件筛选)
         ⽣成器表达式可以直接获取到⽣成器对象. ⽣成器对象可以直接进⾏for循环. ⽣成器具有
         惰性机制.
    
    
    
    
    
  • 相关阅读:
    算法训练 P1103
    算法训练 表达式计算
    算法训练 表达式计算
    基础练习 时间转换
    基础练习 字符串对比
    Codeforces 527D Clique Problem
    Codeforces 527C Glass Carving
    Codeforces 527B Error Correct System
    Codeforces 527A Glass Carving
    Topcoder SRM 655 DIV1 250 CountryGroupHard
  • 原文地址:https://www.cnblogs.com/one-tom/p/9892592.html
Copyright © 2011-2022 走看看