zoukankan      html  css  js  c++  java
  • 十三. Python基础(13)--生成器进阶

    十三. Python基础(13)--生成器进阶

    1 ● send()方法

     

    2 ● send()函数的简单案例

    def fun():

        print('*')

        value = yield 1

        print('**', value)

        yield 2

     

    g = fun()

    print(g.__next__())

    # print(g.__next__()) # ** None

    print(g.send("aaa")) # ** aaa

    # print(g.send("bbb")) # 警示"StopIteration"异常, 因为此时"bbb"没有可以用来赋值的的yield表达式

    '''

    *

    1

    ** aaa

    2

    '''

    # send()和__next__()工作的起始位置是完全相同的

    # send()可以把一个值作为信号量(semaphore)传到函数中去

    # 在生成器执行伊始, 只能先用__next__()或send(None), 因为用send()传递非None参数的时候,在生成器中必须有一个未被赋值的yield表达式

    # __next_()方法以及send()方法的数量 不同多于 yield表达式的数量, 否则警示异常StopIteration.

     

    3 ● 计算累计平均数

    def wrapper(func): # 这个装饰器中只做一件事:g.__next__; 或者next(g), 也就是激活生成器(next是内置函数)

        def inner(*args, **kwargs):

            g = func(*args, **kwargs) # 最好不要跟外面的创建的gen生成器重名

            g.__next__() # 也可以是g.send(None), 用来激活生成器

            return g

        return inner

     

    @wrapper

    def average_func():

        total = 0

        count = 0

        average = 0

        while True: # 这个while True可以让使用者一直使用send方法, 也就是调用这个函数的可生成一个取之不尽用之不竭的生成器, 注意这里不会造成死循环

            value = yield average

            total += value

            count += 1

            average = total/count

     

    gen = average_func()

    print(gen.send(30))

    print(gen.send(50))

    print(gen.send(10))

    '''

    30.0

    40.0

    30.0

    '''

     

    4 ● 列表推导式/字典推导式/集合推导式(没有元组推导式)

    列表推导式:

    print([i**2 for i in range(0, 21, 2) if i < 11]) # [0, 4, 16, 36, 64, 100]

    字典推导式:

    案例①:

    dic = {'k1':'v1', 'k2':'v2'}

    print({dic[key]: key for key in dic})

    # {'v1': 'k1', 'v2': 'k2'}

     

    案例②:

    dic = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}

    dic_new = {k.lower(): dic.get(k.lower(), 0) + dic.get(k.upper(), 0) for k in dic.keys()}

    print(dic_new)

    # {'a': 17, 'b': 34, 'z': 3}

    集合推导式: (自带去重的功能)

    print({i**2 for i in [1, -1, 2]})

    # {1, 4}

     

    5 ● 生成器表达式

    把列表解析的[]换成()得到的就是生成器表达式.

    gen_list = (i**2 for i in range(0, 21, 2) if i < 11)

    for i in gen_list:

        print(i)

    '''

    0

    4

    16

    36

    64

    100

    '''

    dic = {'k1':'v1', 'k2':'v2'}

    gen_a = (key for key in dic)

    gen_b = (key for key in dic.items())

    for i in gen_a:

        print(i)

    for i in gen_b:

        print(i)

    '''

    k1

    k2

    ('k1', 'v1')

    ('k2', 'v2')

    '''

    gen_col = (i**2 for i in {1, -1, 2})

    for i in gen_col:

        print(i)

    '''

    1

    4

    1

    '''

     

    6 ● 面试题1

    def demo():

        for i in range(4):

            yield i

     

    g=demo()

     

    g1=(i for i in g)

    g2=(i for i in g1)

     

    print(list(g1)) # [0, 1, 2, 3]

    print(list(g2)) # []

     

    7 ● 面试题2

    def add(n,i):

        return n+i

     

    def test():

        for i in range(4):

            yield i

     

    g=test()

    for n in [1,10]:

        g=(add(n,i) for i in g) # 生成器推导式

        print(list(g))

     

    # [1, 2, 3, 4]

    # []注意这一步是没有数跟10相加, 因此为空.

    def add(n,i):

        return n+i

     

    def test():

        for i in range(4):

            yield i

     

    g=test()

    for n in [1,10]:

        g=(add(n,i) for i in g)

     

    print(list(g))

     

    '''

    ① 上面的三个g是三个不同的迭代器

    ② 上面一段相当于:

    n = 1

    g=(add(1,i) for i in range(4)) # 1+0+1+2+3=7 # 生成器中的数据没有被获取, 因为生成器只有在被调用的时候才会生成相应的数据(用__next__()、 for、list调用, 或被其它函数调用), 反之就不会生成--惰性运算.

    n = 10

    g=(add(n,i) for i in g)

    print(list(g))

    '''

     

    # [20, 21, 22, 23]

    如果这里是:

    n=1

    g=(add(n,i) for i in g) # 生成器推导式

    n=10

    g=(add(n,i) for i in g)

    n=5

    g=(add(n,i) for i in g)

    print(list(g))

     

    那么相当于运行:

    for n in [1,10,5]:

    g=(add(n,i) for i in g) # 生成器推导式

    print(list(g))

     

    即:

    n=1

    g = (add(n,i) for i in g)

    n=10

    g = (add(n,i) for i in (add(n,i) for i in g))

    n=5

    g = (add(5,i) for i in add(n,i) for i in (add(n,i) for i in g))

     

    # [15, 16, 17, 18]

     

  • 相关阅读:
    python初接触
    Visual Studio Code 必备插件
    C# 基础知识 -- 枚举(Enum)
    Visual Studio : Console.WriteLine(); 快捷键
    C# 调用Outlook发送邮件
    C# Dos、Unix、Mac文件格式之间的相互转换
    Treeview控件失去焦点,将选择的节点设置为高亮显示
    oracle中的Exists、In、Any、All
    TreeView控件如何控制滚动条的位置
    oracle 查看最大连接数与当前连接数
  • 原文地址:https://www.cnblogs.com/ArrozZhu/p/8393698.html
Copyright © 2011-2022 走看看