zoukankan      html  css  js  c++  java
  • 2018.8.13 python中生成器和生成器表达式

    主要内容:

             1、生成器和生成器函数

             2、列表推导式

    一、生成器

             生成器是指就是迭代器,在python中有三种方式来获取生成器:

             1、通过生成器函数

             2、通过各种推导式来实现生成器

             3、通过数据的转换也可以获取生成器

    yield 和return的区别:

          yield分段来执行一个函数,break停止函数执行。

             当程序运行完最后一个yield,那么后面继续进行__next__()程序会报错。

            send使用方法:send和__next__()一样可以让生成器执行到下一个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)      #结果:a =  胡辣汤    大饼
    ret3 = gen.send('狗粮')
    print(ret3)     #结果:b =  狗粮     韭菜盒子
    ret4 = gen.send('猫粮')
    print(ret4)     #结果:c =  猫粮    GAME OVER

    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:
        print(i)
    # 结果:
    # 111
    # 222
    # 333
    # 444
    # 555
    # 666
    for i in list(gen):
        print(i)
    # 结果:
    # 111
    # 222
    # 333
    # 444
    # 555
    # 666

    二、列表推导式,生成器表达式及其他推导式

            首先我们先看一下这样的代码, 给出一个列表, 通过循环, 向列表中添加1-14 :

    lst = []
    for i in range(1, 15):
    lst.append(i)
    print(lst)

           替换成列表推导式:

    lst = [i for i in range(1, 15)]
    print(lst)

           列表推导式的常用写法:

    [ 结果 for 变量 in 可迭代对象 if 条件 ]

            生成器表达式和列表推导式的语法基本上是一样的. 只是把[ ]替换成()

    # 获取1-100内能被3整除的数
    gen = (i for i in range(1,100) if i % 3 == 0)
    for num in gen:
    print(num)
    # 100以内能被3整除的数的平方
    gen = (i * i for i in range(100) if i % 3 == 0)
    for num in gen:
    print(num)
    # 寻找名字中带有两个e的人的名字
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven',
    'Joe'],
    ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    # 不⽤推导式和表达式
    result = []
    for first in names:
    for name in first:
    if name.count("e") >= 2:
    result.append(name)
    print(result)
    # 推导式
    gen = (name for first in names for name in first if name.count("e") >= 2)
    for name in gen:
    print(name)

            生成器表达式和列表推导式的区别:
               1. 列表推导式比较耗内存. 一次性加载. 生成器表达式几乎不占用内存. 使用的时候才分配和使用内存。
               2. 得到的值不一样. 列表推导式得到的是一个列表. 生成器表达式获取的是一个生成器。
           举个栗子:
               同样一篮子鸡蛋. 列表推导式: 直接拿到一篮子鸡蛋. 生成器表达式: 拿到一个老母鸡. 需要鸡蛋就给你下鸡蛋。

    def func():
        print(111)
        yield 222
        print(333)
        yield 444
        print(555)
    g = func()    #生成器g
    g1 = (i for i in g)   #生成器g1,但是g1的数据来源于g
    g2 = (i for i in g1)  #生成器g2,来源g1
    print(list(g))   #获取g中的数据,这时func()才会被执行,结果为:111 333 555 [222,444]
    print(list(g1))#获取g1中的数据,g1的数据来源于g,但是g已经取完了,g1也就没有数据,结果为[]
    print(list(g2))#和g1同理,结果为[]

           深坑----生成器,要值得时候才拿值。

           字典推导式:

    # 把字典中的key和value互换
    dic = {'a': 1, 'b': '2'}
    new_dic = {dic[key]: key for key in dic}
    print(new_dic)
    # 在以下list中. 从lst1中获取的数据和lst2中相对应的位置的数据组成⼀个新字典
    lst1 = ['jay', 'jj', 'sylar']
    lst2 = ['周杰伦', '林俊杰', '邱彦涛']
    dic = {lst1[i]: lst2[i] for i in range(len(lst1))}
    print(dic)

            集合推导式:

    lst = [1, -1, 8, -8, 12]
    # 绝对值去重
    s = {abs(i) for i in lst}
    print(s)

    总结: 推导式有, 列表推导式, 字典推导式, 集合推导式, 没有元组推导式
             生成器表达式: (结果 for 变量 in 可迭代对象 if 条件筛选)
             生成器表达式可以直接获取到生成器对象. 生成器对象可以直接进行for循环. 生成器具有惰性机制。

    def add(a,b):
        return a+b
    def test():
        for r_i in range(4):
            yield r_i
    g = test()
    for n in [2,10]:
        g = (add(n,i) for i in g)
    print(list(g))
    
    # 结果:[20, 21, 22, 23]

     

  • 相关阅读:
    如何卸载服务(转)
    The Frightening Science of Prediction: How Target & 10 Others Make Money Predicting Your Next Life Event(转摘)
    如果你迷恋厚实的屋顶,就会失去浩瀚的繁星
    李开复:移动互联网创业不要总是“入口思维”(转)
    [微言]增长与幸福 zz
    缔元信
    Tabledriven Approach
    北京医院排名 很有用,留下了
    青春期企业如何突围(转)
    意大利罗马&佛罗伦萨 攻略
  • 原文地址:https://www.cnblogs.com/fengchong/p/9470337.html
Copyright © 2011-2022 走看看