• 生成器


    生成器函数

    一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。

    import time
    def genrator_fun1():
        a = 1
        print('现在定义了a变量')
        yield a
        b = 2
        print('现在又定义了b变量')
        yield b
    
    g1 = genrator_fun1()
    print('g1 : ',g1)       #打印g1可以发现g1就是一个生成器
    print('-'*20)   #我是华丽的分割线
    print(next(g1))
    time.sleep(1)   #sleep一秒看清执行过程
    print(next(g1))
    
    初识生成器函数

    从这可以说明生成器可以节省内存

    #初识生成器二
    
    def produce():
        """生产衣服"""
        for i in range(2000000):
            yield "生产了第%s件衣服"%i
    
    product_g = produce()
    print(product_g.__next__()) #要一件衣服
    print(product_g.__next__()) #再要一件衣服
    print(product_g.__next__()) #再要一件衣服
    num = 0
    for i in product_g:         #要一批衣服,比如5件
        print(i)
        num +=1
        if num == 5:
            break
    
    #到这里我们找工厂拿了8件衣服,我一共让我的生产函数(也就是produce生成器函数)生产2000000件衣服。
    #剩下的还有很多衣服,我们可以一直拿,也可以放着等想拿的时候再拿
    
    初识生成器二

    生成器的应用

    import time
    
    
    def tail(filename):
        f = open(filename)
        f.seek(0, 2) #从文件末尾算起
        while True:
            line = f.readline()  # 读取文件中新的文本行
            if not line:
                time.sleep(0.1)
                continue
            yield line
    
    tail_g = tail('tmp')
    for line in tail_g:
        print(line)
    
    生成器监听文件输入的例子

    对于 send的解释

    def generator():
        print(123)
        content = yield 1
        print('=======',content)
        print(456)
        yield2
    
    g = generator()
    ret = g.__next__()
    print('***',ret)
    ret = g.send('hello')   #send的效果和next一样
    print('***',ret)
    
    #send 获取下一个值的效果和next基本一致
    #只是在获取下一个值的时候,给上一yield的位置传递一个数据
    #使用send的注意事项
        # 第一次使用生成器的时候 是用next获取下一个值
        # 最后一个yield不能接受外部的值

    计算移动平均值

    def averager():
        total = 0.0
        count = 0
        average = None
        while True:
            term = yield average
            total += term
            count += 1
            average = total/count
    
    
    g_avg = averager()
    next(g_avg)
    print(g_avg.send(10))
    print(g_avg.send(30))
    print(g_avg.send(5))
    
    计算移动平均值(1)

    计算移动平均值(2)_预激协程的装饰器

    def init(func):  #在调用被装饰生成器函数的时候首先用next激活生成器
        def inner(*args,**kwargs):
            g = func(*args,**kwargs)
            next(g)
            return g
        return inner
    
    @init
    def averager():
        total = 0.0
        count = 0
        average = None
        while True:
            term = yield average
            total += term
            count += 1
            average = total/count
    
    
    g_avg = averager()
    # next(g_avg)   在装饰器中执行了next方法
    print(g_avg.send(10))
    print(g_avg.send(30))
    print(g_avg.send(5))
    
    计算移动平均值(2)_预激协程的装饰器

    yield from

    def gen1():
        for c in 'AB':
            yield c
        for i in range(3):
            yield i
    
    print(list(gen1()))
    
    def gen2():
        yield from 'AB'
        yield from range(3)
    
    print(list(gen2()))
    
    yield from

    列表推倒式和生成器表达式

    总结:

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

    2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

    3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:

    sum(x ** 2 for x in range(4))

    而不用这样例子:

    sum([x ** 2 for x in range(4)])

    列表推导式

    例一:30以内所有与能被3整除的数

    multiples = [i for i in range(30) if i % 3 is 0]
    print(multiples)
    # Output: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

    例二:30以内所有能被3整除的数的平方

    def squared(x):
        return x*x
    multiples = [squared(i) for i in range(30) if i % 3 is 0]
    print(multiples)

    例三:找到嵌套列表中名字含有两个‘e’的所有名字

    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    
    print([name for lst in names for name in lst if name.count('e') >= 2])  # 注意遍历顺序,这是实现的关键

    字典推到式

    例一:将一个字典的key和value对调

    mcase = {'a': 10, 'b': 34}
    mcase_frequency = {mcase[k]: k for k in mcase}
    print(mcase_frequency)

    例二:合并大小写对应的value值,将k统一成小写

    mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
    mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()}
    print(mcase_frequency)

    集合推导式

    squared = {x**2 for x in [1, -1, 2]}
    print(squared)
    # Output: set([1, 4])
  • 相关阅读:
    【C++标准库】C++11新特性
    使用线程池
    Halcon相机硬触发采集图片
    C#之线程同步
    多线程之异常处理
    java基础 Arrays
    java基础 static关键字
    java基础 String
    c# 更新web.config
    java 基础
  • 原文地址:https://www.cnblogs.com/LLBFWH/p/9960791.html
Copyright © 2020-2023  润新知