• python 生成器


    ---恢复内容开始---

    回顾下的 迭代器:

      可迭代协议:内部含有__iter__()方法的值/变量都是可迭代的

        可迭代变量 点__iner__()返回一个迭代器

      迭代器特点: 节省内存,惰性运算,一次取值,只按照顺序取

      所有的迭代器都是可迭代,反之 不成立

      for循环和迭代器的关系,无论是迭代器换是可迭代都可以被for循环,

                  如果直接循环迭代器 循环一次就没了

                如果循环非迭代器,那么每次循环都相当于从头到尾的循环

                是因为在for循环中的所有非迭代器都会通过iter生成一个新的迭代器

    一 生成器 (本质就是迭代器,生成器由生成器函来创建或者通过生成器表达式来创建)
      1.先看简单函数

    def func():
    print("111")
    return 222
    ret = func() # 结果为111 
    print(ret)  # 结果为222

    简单来说将函数中的return换成yield就是生成器:

    def func():
    print("111")
    yield 222 
    ret = func()
    print(ret) #此时结果为 <generator object func at 0x000001C11A730EB8>  生成器地址 

    生成器的本质是迭代器. 所以. 我们可以直接执行__next__()来执行

    def func():
    print("111")
    yield 222
    gener = func() #   结果 111 这个时候函数不会执⾏. 而是获取到生成器器
    ret = gener.__next__() # 这个时候函数才会执行. yield的作用和return一样. 也是返回
    数据
    print(ret) #结果222

    简单例子 : 

    def funt():
    #     lst=[]
    #     for i in range(10000):
    #         lst.append("衣服%s" % i)
    #     return lst
    # lst=funt()
    # print(lst) #得到10000件衣服 没地方放 换得找个仓库 :占内存

    优化

    def funt():
        for i  in range(10000):
            yield "衣服%s" % i
    gen=funt()
    # print(gen)
    a1=gen.__next__()
    a2=gen.__next__()
    a3=gen.__next__()
    a4=gen.__next__()
    a5=gen.__next__()
    a6=gen.__next__()
    print(a1)
    print(a2)
    print(a3)
    print(a4)
    print(a5)
    print(a6)   # 要几件拿几件 不够 我想成批拿

    再优化:

    ef funt():                                                  
        lst=[]
        for i in  range(1,10000):
            lst.append( '衣服%s' % i)
            if i%50==0:
                yield lst
                lst=[]
    
    ret=funt() #生成器
    a=ret.__next__()
    print(a)
    a2=ret.__next__()
    print(a2) 
    def func():
        for i in range(1, 10000):
            yield "衣服%s" % i
    
    ret=func()
    for i in range(50):
        a=ret.__next__()
        print(a,end='')

    生成器:本质是迭代器, 写法和迭代器不一样. 用法和迭代器一样
    # 生成器函数: 函数中带有yield, 执行生成器函数的时候返回生成器。而不是执行这个函数
    # def func():
    # print("你好啊, 我叫赛利亚,")
    # yield "西岚的武士刀" # return 和yield都可以返回数据
    #
    # ret = func() # generator ret是一个生成器
    # print(ret)
    # s = ret.__next__() # 当执行到__next__()的时候, 函数才真正的开始执行
    # print("接受到的是", s)

    例子2..

    def func():
        print("打开手机")
        print("打开陌陌")
        yield "手机"
        print("约妹子")
        print("出来喝喝茶")
        yield "电脑"
        print("我加了一句话")
    gen = func() # 生成器
    ret1 = gen.__next__()
    print(ret1)
    ret2 = gen.__next__()
    print(ret2)
    ret3 = gen.__next__()  # 找不到最后一个yield 会报错
    print(ret3)
     

    2.send ()  :   send() 也可以实现类似__next__()的效果, send()可以给上一个yield传值

    def func():
        print("韭菜盒子")
        a = yield "哇哈哈"
        print("肉包子", a)
        b = yield "脉动"
        print("锅包肉", b)
        yield "冰红茶"
    gen = func()
    ret = gen.__next__()
    print(ret)
    
    ret = gen.send("刘伟") # 给上一个yield传值
    print(ret)
    
    ret = gen.send("刘德华") # 给上一个yield传值
    print(ret) 

    结果:

    韭菜盒子
    哇哈哈
    肉包子 刘伟
    脉动
    锅包肉 刘德华
    冰红茶

     

     send()和__next__()的区别:

    send()不可以用在开头

    send可以给上一个yield传值,不能给最后一个yield传值

    返回值写法:

    def func():
    yield "麻花藤" yield "李彦宏" yield "马云" yield "刘强东" gen=func() # a=gen.__next__() # print(a) print(gen.__next__()) # 麻花藤 print(gen.__next__()) #李彦宏" print(gen.__next__())#马云"


    生成器本质是迭代器
    print("__iter__" in dir(gen)) #所以可以使用for循环

    for el in gen:
     print(el)

    
    

    lst = list(gen) # 把生成器中的每一个数据拿出来组合成一个列表
    # print(lst)

    二 推导式:

    列表的推倒式:[结果 for循环 if筛选]

    例子1

    常规算法
    lst = [] for i in range(1, 15): lst.append(i) print(lst)
    推倒式写法:

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

    # 获取1-100内能被3整除的数

    lst = [i for i in range(1, 101) if i % 3 == 0]

    100以内能被3整除的数的平⽅

    lst = [i*i for i in range(1, 101) if i % 3 == 0]

     names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],
    #  ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    寻找名字中带有两个e的⼈的名字
    
    lst = [name for first in names for name in first if name.count("e") >= 2 ]
    # print(lst)
    
    
    
    
    for name in names:
    #     for nam in name:
    #         if nam.count('e')>=2:
    #             print(nam)

    字典推倒式  {key: value for循环 if 筛选}

    ic={"张无忌":'九阳神功',"乔峰":"收音机","楚留香":''}
    # d={dic[k]:k for k in dic}
    # print(d)

    lst1 = ["东北", "陕西", "山西", "开封", "杭州", "广东", "济南"]
    # lst2 = ['大拉皮', "油泼面", "老陈醋", "灌汤包", "西湖鲤鱼", "早茶", "胶东一锅鲜"]


    dic = {lst1[i]:lst2[i] for i in range(len(lst1))} # print(dic) dic={} for i in range(len(lst1)): for a in range(len(lst2)): dic[lst1[i]]=lst2[i] print(dic)

    集合推倒式 (无序 不重复 可哈西)  {key for if}

    lst = ["周杰伦","周伯通","周润发","周伯通","周笔畅","周伯通","周星驰","周伯通"]
    # s = {el for el in lst}
    # print(s)

    三 生成器表达式( 生成器表达式可以直接创建生成器)

     gen = (i for i in range(10)) # generator
     print(gen.__next__())
     print(gen.__next__())
     print(gen.__next__()) #结果 0 1 2
    
    
      print('__iter__'in dir(gen))  # true

    生成器表达式: 记录一下代码。 然后每次需要的时候去生成器中执行一次这个代码
    # 列表推导式: 一次性把所有的数据创建出来, 容易产生内存浪费
    # 特性:
    # 1. 节省内存
    # 2. 惰性机制
    # 3.只能向前。

     

    ---恢复内容结束---

  • 相关阅读:
    课程一(Neural Networks and Deep Learning),第一周(Introduction to Deep Learning)—— 1、经常提及的问题
    递归、字节流、文件复制_DAY20
    IO概述、异常、File文件类_DAY19
    某书2018笔试题之薯券
    某书2018笔试题之翻转数字
    某书2018笔试题之字符串中最大子数字串
    批量发货的启示
    为什么易燥易怒以及柔润相处的练习
    编程漫谈(十五):编程与软件开发
    使用函数式编程消除重复无聊的foreach代码(Scala示例)
  • 原文地址:https://www.cnblogs.com/systemsystem/p/9672130.html
Copyright © 2020-2023  润新知