zoukankan      html  css  js  c++  java
  • 生成器和推导式

    一. 推导式

    列表, 字典, 集合有推导式, 元组没有推导式

    列表推导式: lst = [i for i in range(10) if i % 2 == 0]

    字典推导式: dic = {k:v for k,v in func() if k>v}    # def func():  yield 2,1  yield 3,1  yield 4,1     (yield 的第一个值不能相同, 因为字典的键会传不进去)

    集合推导式: se = {i for i in range(5)}

    a = (i for i in range(10)   # 这不是元组, 这是生成器的表达式, 具有惰性. 

    可以用for循环, while循环, list[], tuple(), set(), 来遍历生成器

    二. 生成器

    生成器的本质是迭代器

    生成器的特点和迭代器一样, 取值方式一样, __next__(), send(), send()可以给上一个yield传值

    生成器一般由生成器函数或生成器表达式来创建

    超过yield的个数会报错, 但可以用try: except StopIteration兜着

    生成器函数: 

    和普通函数没有区别, 函数里面含有yield.

    生成器函数在执行时, 默认不会执行函数, 而是返回生成器

    生成器函数通过生成器的__next__()分段执行这个函数. 

    可以用send()给上一个yield传值, 不能在开头(没有上一个yield)

    f = func()拿到的是生成器, 不会执行函数. 

    yield会停止执行函数, 下次再分段执行函数.

    如果不使用f = func()来获取生成器, 每次用func().__next__()来获取, 每次都是获取的到第一个yield的值

    def func():
        a = yield 1
        print(a)
        b = yield 2
        print(b)
        c = yield 3
        print(c)
        yield 4
    
    f = func()
    # ===================================== 第一个输出方法 ===================================== print(f.__next__()) print(f.send(123)) print(f.send(234)) print(f.send(345)) 输出 1 123 2 234 3 345 4
    # ===================================== 第二个输出方法 ===================================== print(f.__next__(),f.send(123),f.send(234),f.send(345)) 输出: 123 234 345 1 2 3 4

    生成器表达式:

    gen = (i for i in range(10) if i >= 5)

    gen = (func(i) for i in range(10) if i >= 5)

    gen = ('xxxxx{}".format(i) for i in range(10))

     

    特性:

    惰性机制

    只能向前

    节省内存

    题:

    def func():
        print(111)
        yield 222
        yield 333
    
    g = func()                   
    g1 = (i for i in g)     # g1拿到的还生成器表达式, 不会执行表达式, 在后面的list(g1)才会执行表达式
    g2 = (i for i in g)
    
    print(list(g))          # list(g)拿到的是g的所有的yield的值, 本来g是不会自动执行的, 但是list使g 
                            # 自动执行了, g执行完了以后, g是生成器, 不能回退, 所以g1和g2再执行g的时候
                            # 就拿不到值了
    print(list(g1))
    print(list(g2))         # 如果g2先执行, g2就会遍历完g中的值, list又会便利完g2的值, 所以g1再遍历g 
                            # 的值, 或者list再遍历g的值就拿不到值了
    def  add(a, b):
        return a + b
    
    def test():
        for i in range(4):
            yield i                        # yield 0,1,2,3
    
    g = test()
    
    for n in [2,10]
        g = (add(n, i) for i in g)         # 拿到g时不会遍历生成器
    print(list(g))
     # ===================================== g的运行 =====================================
    for n in [2,10]
        g = (add(n, i) for i in g)
    n = 2
    # g = (add(n = 2, i) for i in g)    # i的值现在拿不出来, 因为g没有被遍历, 所以add函数无法执行
                                        # 所以add函数还是add(n, i)
    n = 10
    # g = (add(n = 10, i) for i in (add(n = 10, i) for i in g)) # 由于add函数的n上次未执行, 
                                        # 所以add函数还是add(n, i), 所以这次n = 10时, n就被重新
                                        # 赋值了
    list(g) 
    # g = add(10, i) for i in (add(10, i) for i in 0.1.2.3))
    
     # ===================================== 改一下 =====================================d
    
    def  add(a, b):
        return a + b
    
    def test():
        for i in range(4):
            yield i                        # yield 0,1,2,3
    
    g = test()
    
    for n in [2,10]
        g = [add(n, i) for i in g]  
    print(list(g))
     # ===================================== g的运行 =====================================
    n = 2
    g = [2,3,4,5]       # 列表的推导式, 不是生成器的表达式
    n = 10
    g = [12,13,14,15]
    
  • 相关阅读:
    Mybatis整理
    Spring获取json和表单
    Mqtt(paho)重连机制
    Redis无法获取资源(Could not get a resource from the pool)
    SSM+Maven+Redis框架学习
    第一章 Zookeeper理论基础
    RocketMQ和Kafka对比
    Kafka工作原理与过程
    Kafka介绍
    JVM调优
  • 原文地址:https://www.cnblogs.com/NachoLau/p/9469318.html
Copyright © 2011-2022 走看看