zoukankan      html  css  js  c++  java
  • 12_python_生成器

    一、生成器

     

      python中有三种方式获取生成器
      (1)通过生成器函数
      (2)通过各种推导式来实现生成器
      (3)通过数据的转换也可以获取生成器
     
      1、只要函数中存在了yield,那么这个函数就是一个生成器函数,生成器实质就是迭代器,所以生成器可以直接执行__next__()
     1 def func():
     2  print("111")
     3  yield 222
     4 gener = func() # 这个时候函数不会执行. 而是获取到⽣成器
     5 ret = gener.__next__() # 这个时候函数才会执行. yield的作用和return一样. 也是返回数据
     6 ret = gener.__next__() # 报错StopIteration
     7 print(ret)
     8 结果:
     9 111
    10 222
      yield是分段来执⾏⼀个 函数. return呢? 直接停⽌执⾏函数。种使⽤⽣成器. ⼀次就⼀个. ⽤多少⽣成多少. ⽣成器是⼀个⼀个的指向下⼀个. 不会回去, __next__()到哪, 指针就指到哪⼉. 下⼀次继续获取指针指向的值. 
     
      2、send()
      send和__next__()⼀样都可以让⽣成器执⾏到下⼀个yield. 
     1 def eat():
     2     print("我吃什么啊")
     3     a = yield "馒头"
     4     print("a=",a)
     5     b = yield "烧饼"
     6     print("b=",b)
     7     c = yield "菜盒子"
     8     print("c=",c)
     9     yield "GAME OVER"
    10 gen = eat() # 获取生成器
    11 ret1 = gen.__next__()
    12 print(ret1)
    13 ret2 = gen.send("胡辣汤") # 给上一个yield传值,也就是a
    14 print(ret2)
    15 ret3 = gen.send("狗粮")
    16 print(ret3)
    17 ret4 = gen.send("猫粮")
    18 print(ret4)
    19 结果:
    20 我吃什么啊
    21 馒头
    22 a= 胡辣汤
    23 烧饼
    24 b= 狗粮
    25 菜盒子
    26 c= 猫粮
    27 GAME OVER
      3、send和__next__()区别: 
          (1). send和next()都是让⽣成器向下走⼀次 
          (2). send可以给上⼀个yield的位置传递值, 不能给最后⼀个yield发送值. 在第⼀次执⾏⽣成器代码的时候不能使⽤send()
     
      4、⽣成器可以使⽤for循环来循环获取内部的元素:
     1 def func():
     2     print(111)
     3     yield 222
     4     print(333)
     5     yield 444
     6     print(555)
     7     yield 666
     8 gen = func()
     9 for i in gen:
    10     print(i)
    11 结果:
    12 111
    13 222
    14 333
    15 444
    16 555
    17 666

      执行生成器的方式:

     1 第一种
     2 def func()
     3     print('hello')
     4     yield 111
     5 gen = func()
     6 for i in gen:
     7     print(i)
     8 第二种
     9 lst = list(gen)
    10 print(lst)
    11 第三种
    12 gen.__next__()

    二、推导式

      1、列表推导
         [ 结果 for 变量 in 可迭代对象 if 条件 ]
    1 # 100以内能被3整除的数的平方
    2 gen = (i * i for i in range(100) if i % 3 == 0)
    3 for num in gen:
    4  print(num)
      2、字典推导式
        {key: value for循环 if 筛选}
    1 # dic = {"张无忌":"九阳神功", "乔峰":"降龙十八掌", "楚留香":"帅"}
    2 # d = {dic[k]: k for k in dic}
    3 # print(d)
      3、集合推导式
         {key for if}
    1 # lst = ["周杰伦","周伯通","周润发","周伯通","周笔畅","周伯通","周星驰","周伯通"]
    2 # s = {el for el in lst}
    3 # print(s)

      ⽣成器表达式和列表推导式的区别:

        1. 列表推导式比较耗内存. ⼀次性加载. ⽣成器表达式⼏乎不占⽤内存. 使⽤的时候才分 配和使⽤内存

        2. 得到的值不⼀样. 列表推导式得到的是⼀个列表. ⽣成器表达式获取的是⼀个⽣成器.⽣成器的惰性机制: ⽣成器只有在访问的时候才取值

  • 相关阅读:
    LeetCode 32. 最长有效括号(Longest Valid Parentheses)
    LeetCode 141. 环形链表(Linked List Cycle)
    LeetCode 160. 相交链表(Intersection of Two Linked Lists)
    LeetCode 112. 路径总和(Path Sum)
    LeetCode 124. 二叉树中的最大路径和(Binary Tree Maximum Path Sum)
    LightGBM新特性总结
    sql service 事务与锁
    C#泛型实例详解
    C# 中的委托和事件(详解)
    C# DateTime日期格式化
  • 原文地址:https://www.cnblogs.com/hq82/p/9670332.html
Copyright © 2011-2022 走看看