zoukankan      html  css  js  c++  java
  • python全栈闯关--14-生成器进阶

    1、复习

    def generator():
        print('1')
        yield 'a'
        print('2')
        yield 'b'
        print('3')
    
    g = generator()
    res = g.__next__()  # 第一个__next__执行到第一个yiled停止, 并返回第一个yiled处的值
    print(res)
    res = g.__next__()  # 第二个__next__执行到第二个yiled停止, 并返回第二个yiled处的值
    print(res)
    res = g.__next__()  # 虽然执行了print('3')操作,但是报错,因为后续没有yiled了,为了避免报错,可以结尾加上yiled
    print(res)

    2、send

    def generator():
        print('1')
        num = yield 'a'  # 此处如果继续执行,使用__next__触发,num将会被复制None。使用send,num将会接收seed的值
        print("seed num:%s" % num)
        print('2')
        yield num * 2
        print('3')
        yield
    
    g = generator()
    res = g.__next__()  # 第一个__next__执行到第一个yiled停止, 并返回第一个yiled处的值
    print(res)
    res = g.send(10)  # 发送值给生成器内部,并返回下一个yiled处的值
    print(res)
    res = g.__next__()  # 虽然执行了print('3')操作,但是报错,因为后续没有yiled了,为了避免报错,可以结尾加上yiled
    print(res)  # 由于yield没有返回值,返回None
    • send的获取下一个值得能力和next一致。
    • send时,传递值给当前send位置的yield,并执行代码带一个yiled处停止
    • 使用send注意事项:
      • 第一次获取生成器的值时,使用next,不能以开始就是用send
      • 最后一个yiled的位置,不能使用send,否则会报错“StopIteration”

    3、yield from

    yiled from 可以从生成器函数中,依次返回各个值

    def func():
        s = 'abcd'
        num = '1234'
        yield from s
        yield from num
    
    for i in func():
        print(i)

     4、生成器表达式

    生成器表达式:在一行代码中,完成生成器

    结构: (元素 for 元素 in 元素范围)

    生成器表达式:

    g = (i for i in range(10))
    
    for i in g:
        print(i)

    不调用不返回值,几乎不暂用内存

    如果把括号改成方括号,则是列表推导式

    g = [i for i in range(10)]
    print(g)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    区别是列表推导式执行完毕时,列表就生成了,已经分配内存

    5、各种推导式

    列表推导式

    [每一个元素或者和元素相关的操作 for 元素 in 可迭代数据类型]   #遍历之后挨个处理

    [满足条件的元素相关操作 for 元素 in 可迭代数据类型 if 元素相关的操作]  #筛选

    # 30以内所有能被3整除的数
    ret = [i for i in range(30) if i%3 == 0]
    print(ret)
    
    # 30以内所有能被3整除的数的平方
    ret = [i*i for i in range(30) if i%3 == 0]
    print(ret)
    
    # 找到嵌套列表中名字含有两个‘e’的所有名字
    
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    ret = [name for lst in names for name in lst if name.count('e') == 2]
    print(ret)

    字典推导式:

    # 例一:将一个字典的key和value对调
    mcase = {'a': 10, 'b': 34}
    dic = { mcase[k]:k for k in mcase}
    print(dic)
    
    # 例二:合并大小写对应的value值,将k统一成小写
    mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
    dic = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase}
    print(dic)

    集合推导式:

    #集合推导式,自带结果去重功能
    squared = {i*i for i in [1, -1, 2]}
    print(squared)

    6、练习

    # 获取移动平均值
    def move_arg():
        sum = 0
        count =0
        avg = 0
        while 1:
            num = yield avg
            sum += num
            count += 1
            avg = sum / count
    
    g = move_arg()
    print(g.__next__())
    print(g.send(10))
    print(g.send(20))
    print(g.send(30))
    print(g.send(10))

    使用装饰器,完善上述代码,是代码,使代码运行更加顺畅

    def init(f):
        def warp():
            g = f()  # 调用生成器函数,得到一个生成器
            g.__next__()  # 预激活,执行next
            return g  # 返回激活器
        return warp
    
    @init
    def move_arg():
        sum = 0
        count =0
        avg = 0
        while 1:
            num = yield avg
            sum += num
            count += 1
            avg = sum / count
    
    
    g = move_arg()
    # 3.处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕
    def check_file(file,find_str):
        with open(file,encoding ='utf-8') as f :
            for i in f:
                if find_str in i:
                    yield i
    
    g = check_file("总结复习.py",'迭代器')
    for i in g:
        print(i, end='')
    # 4.写生成器,从文件中读取内容,在每一次读取到的内容之前加上‘***’之后再返回给用户。
    def get_line(file):
        with open(file,encoding ='utf-8') as f:
            for i in f:
                yield "***" + i
    
    
    g = get_line("总结复习.py")
    for i in g:
        print(i, end='')

    7、总结和复习

    • 迭代器和生成器
    • 迭代器
      • 可迭代协议: 含有__iter__方法的都是可迭代的
      • 迭代器协议:含有__next__和__iter__方法的都是迭代器
      • 特点:
        • 节省内存
        • 可以方便的遍历去到每一个值
    • 生成器——本质是一个迭代器
      • 生成器函数:
      • 含有yield关键字的都是迭代器
      • 生成器的特点:
        • 调用函数之后函数内的代码不会执行,返回生成器
        • 每次从生成器中取一个值,都会执行一段代码,到yiled就停止
      • 如何从生成器中取值:
        • for:如果没有break会一直取完
        • next:一次只取一个值
        • send:不能用在第一个和最后一个,取下一个值得时候,给上一个值得位置,传递一个新的值
        • 数据类型强制转换:会一次性得到所有的值,暂用内存
      • 生成器表达式:
        • (符合条件的元素i for i in 可迭代 if 条件)
  • 相关阅读:
    第一周实习工作总结
    service---七月十九号实验
    安卓常用链接
    Activity + 基础UI
    七月十四日安卓学习笔记
    安卓组件学习笔记
    剑指:数组中出现次数超过一半的数字
    剑指:二叉搜索树与双向链表
    剑指:二叉树中和为某一值的路径
    剑指:二叉搜索树的后序遍历序列
  • 原文地址:https://www.cnblogs.com/zxw-xxcsl/p/11741755.html
Copyright © 2011-2022 走看看