zoukankan      html  css  js  c++  java
  • python中的生成器

    一.生成器(generator)

    生成器的实质就是迭代器
    生成器表达式:

    1 def func():
    2     print('111')
    3     yield 222
    三种执行生成器的方式
    1.通过g.__next__(),send()来实现生成器
    1 def func():
    2     print(111)
    3     yield 222
    4     # yield 112
    5 g=func()
    6 print(g.__next__())
    2.通过各种推导式来实现生成器(for)
    1 def func():
    2     print(111)
    3     yield 222
    4     # yield 112
    5 g=func()
    6 g1=[i for i in func()]
    7 print(g1)
    3.通过数据的转换也可以实现生成器:list(),tuple()
    1 def func():
    2     print(111)
    3     yield 222
    4     # yield 112
    5 g=func()
    6 # g1=[i for i in func()]
    7 print(list(g))   #获得列表
    yield和return的区别:
    yield是分段执行一个函数,return是直接停止执行函数
     1 def func():
     2     print('111')
     3     yield 222
     4     print('333')
     5     yield 444
     6 gener=func()
     7 ret=gener.__next__()#222
     8 print(ret)
     9 ret2=gener.__next__()#444
    10 print(ret2)
    11 ret3=gener.__next__()#    ret3=gener.__next__()   __next__()如果多了会报错
    12 StopIteration
    13 print(ret3)
    生成器省内存的原因:
    1 def cloth():
    2     lis=[]
    3     for i in range(10000):
    4         lis.append(i)
    5     print(lis)
    6 cloth()#c此时lis列表将所有的值全部都拿出来了,所以非常耗内存
    1 def cloth():
    2     for i in range(10000):
    3         yield i
    4 gener=cloth()
    5 print(gener.__next__())
    6 print(gener.__next__())
    7 print(gener.__next__())#一次就一个 用多少生成多少
    send()方法:

     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 gener=eat()
    11 ret=gener.__next__()
    12 print(ret)
    13 ret2=gener.send('胡辣汤')
    14 print(ret2)
    15 ret3=gener.send('猫粮')
    16 print(ret3)
    17 ret4=gener.send('大鱼大肉')
    18 print(ret4)
    send() 给上一个yield传值, 不能再开头(没有上一个yield), 最后一个yield也不可以用send()

    send()和__next__()的区别:
    send和next都是让生成器向下走一次,但是send可以给上一个yield的位置传值

    二.推导式

    2.1列表推导式
    1 lst=[i for i in range(10) if i%2==0]
    2 print(lst)
    写法:[结果 for循环 条件]
    1 lis=['我是天下第%s美' % i for i in range(1,5) if i%2==1]
    2 print(lis)
    2.2.字典推导式
    1 dic={'第一美':'','第一帅':'靳文博'}
    2 dic_new={value:key for key,value in dic.items()}
    3 print(dic_new)
    写法同列表推导式

    2.3集合推导式
    1 lst=[1,1,2,2,3,4,5]
    2 set={i for i in lst}
    3 print(set)  #自带去重复的功能
    写法同列表推导式

    2.4 生成器表达式
    生成器表达式的语法与以上三个推导式的语法基本上是一样的,只是把[]换成()
    1 gener=(i for i in range(5))
    2 print(gener)  #<generator object <genexpr> at 0x000001D161B6CF68>  结果告诉我们这是一个生成器
    获取10以内能被3整除的数
    1 gener=(i for i in range(10) if i%3==0)
    2 for i in gener:
    3     print(i)
    生成器表达式和列表推导式的区别:
    1.列表推导式比较耗内存,一次全加载出来,生成器表达式几乎不耗内存,使用一个出来一个

    生成器的惰性机制
    1 def func():
    2     print('111')
    3     yield 222
    4 g=func()   #获取生成器
    5 g1=(i for i in g)   #也是生成器
    6 g2=(i for i in g1)   #也是生成器
    7 print(tuple(g))
    8 print(list(g1))   #执行的时候源头已经没有数据了,生成器无法后退
    9 print(list(g2))
    例子
     1 def add(a,b):
     2     return  a+b
     3 
     4 def test():
     5     for i in range(4):
     6         yield i
     7 g=test()
     8 
     9 for n in [2,10]:
    10     g=(add(n,i)  for i in g)    #此时的n不会带值
    11 
    12 print(list(g))#归根结底还是惰性机制,这里只有 list()才会拿值
    13 [20, 21, 22, 23]

    小知识点1:

    如何把一行代码换成两行:

    在你想换行的地方后面加,然后接着写就行了

     

  • 相关阅读:
    《.NET分布式应用程序开》读书笔记 第一章:理解分布式架构
    一个DataSet的工具类,可以将DataTime的Time部分去掉,主要在序列化Xml时有用.
    Microsoft SQL Server 2005技术内幕系列书籍
    COM+客户端部署发现
    PowerDesigner中三种模型的转换关系图
    将ASP.NET页面内容输出到字符串中
    在WinForms中隐藏Crystal Report的[MainReport]标签页
    qmake常用语法一
    MinGW简介
    Qt的prx文件
  • 原文地址:https://www.cnblogs.com/shanghongyun/p/9469840.html
Copyright © 2011-2022 走看看