zoukankan      html  css  js  c++  java
  • python学习笔记 day14 生成器进阶

    生成器的本质就是迭代器,因为生成器含有__iter__()方法和__next__()方法; 

    带有yield关键字的函数都是生成器函数,生成器函数被调用时会返回一个生成器,但是函数体内的代码不会被执行,只有生成器调用__next__()方法时,才会被执行但是遇到yied关键字处,函数就暂停,等下一次该生成器再调用.__next__()函数时,下面的代码才会被继续执行;

    其实生成器效率还是比较高的(个人理解),比如我们现在需要打印“哈哈哈哈哈”,需要打印200万,如果使用list存储,然后再打印,简直太浪费内存了,我们不可能一次存储完所有之后,再一次性全部打印,就好像QQ聊天,我们 输入一段内容,及时发送给i对方,而不是等所有内容编辑完成一次性发给别人;

    def generator():
        for i in range(2000000):
            yield "哈哈哈哈%d"%i
    g=generator()
    for i in g:
        print(i)

    运行结果:

    生成器就是边调用边取值~

    生成器函数获取值的三种方法:

    1.可以使用.__next__()方法调用来获取一个值;

    2.也可以使用for循环,来打印出所有的值;

    3.当然也可以使用强制类型转换(比如list(generator)就会打印出生成器所有的值)-------占用内存

    写一个生成器,实现:有一个文件,从文件中分段读取内容可以一行一行读,也可以几个字节读取,要求读出来的结果前面加上*****在返回给调用者;

    def generator():
        with open("info",mode='r',encoding='utf-8') as file:
            while True:
                line=file.readline()
                # line=file.read(20)
                if line.strip():
                    yield "*****"+line.strip()
    
    g=generator()
    for i in g:
        print(i)

    运行结果:

     send()方法

    讲send()方法之前,先来看一段代码:

    def generator():
        print('a')
        yield 1
        print('b')
        yield 2
        print('3')
    g=generator()
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())

    运行结果:

    虽然最后一个yield后面的代码print(3)被打印了,可是却报错了,因为执行了三个.__next__() 然而生成器函数内部只有两个yield可以被__next__()方法调用~

    所以一般不要再最后一个yield后面写代码,会报错;

    但是使用for 循环打印却不会报错,而且还可以输出最后一个yield后面的代码呢~

    def generator():
        print('a')
        yield 1
        print('b')
        yield 2
        print('3')
    g=generator()
    for i in g:
        print(i)

    运行结果:

     现在来看send()方法:

    def generator():
        print('a')
        yield 1
        print("b")
        yield 2
        
    g=generator()
    print(g.__next__())
    print(g.send(None))

    运行结果:

    1. 从运行结果上来看,send()方法和.__next__()方法是一样的,都是可以从上一个yield位置之后的代码开始执行,遇到下一个yield就停止,将值返回给g.__next__()或者g.send()处,以便打印;

    def generator():
        print('a')
        value=yield 1
        print(value)
        print('b')
        yield 2
    g=generator()
    print(g.__next__())
    print(g.send('我可以把值返回给上一个yield停止的位置处'))

    运行结果:

    执行过程是这样的:首先g.__next__()方法会从函数体开始执行,然后遇到第一个yield就停止,然后g.send()方法开始执行,从上一个yield停止的位置开始,然后把值传给上一个yield停止的位置也就是value(因为value=yield 1遇到赋值号,先执行等号右侧,然后在进行赋值,__next__()方法刚好执行到等号右侧就停止了,send()方法接着从停止的位置执行,就会把里面的值传递给赋值号左边,然后继续执行后面的代码,知道遇到下一个yield就停止了,将yield的结果返回,这一点跟__next__()方法很像~)

    也就是   2.send()方法除了可以跟__next__()方法一样从上一个yield停止的地方开始执行,一直到下一个yield的地方停止外,还可以对上一个yield停止的位置处传数据!!

     最后需要注意的是,3.生成器在取值时,第一个值必须由.__next__()方法获得;最后一个yield不传值!!因为你传值,后面也没有yield了 也就没法用__next__()方法或者send()方法取值了

    除非:

    def generator():
        print('a')
        value1=yield 1
        print('send()方法给在第一个yield处传递的值',value1)
        print('b')
        value2=yield 2
        print("send()在第二个yield处传递的值",value2)
        yield
    g=generator()
    print(g.__next__())
    print(g.send('哈哈哈'))
    g.send('嘻嘻嘻')

    运行结果:

    talk is cheap,show me the code
  • 相关阅读:
    关于栈部分知识点
    面向对象--四则运算
    转型第一步
    输入输出文件版本——计算题
    作业二
    2017《面向对象程序设计》课程作业一
    第四次作业
    light oj 1079
    Light oj 1080
    Codeforces 486B OR in Matrix【水题】
  • 原文地址:https://www.cnblogs.com/xuanxuanlove/p/9588432.html
Copyright © 2011-2022 走看看