您的位置:澳门新葡8455最新网站 > 编程教学 > 揭破yield关键字的秘密面纱

揭破yield关键字的秘密面纱

发布时间:2019-11-06 06:58编辑:编程教学浏览(107)

    写在序言

    1.迭代

    在知情生成器在此之前,先清楚迭代。

    反复会映珍视帘,python函数中带有yield关键字,那么yield是怎么,有怎样效果与利益?

    1.1 迭代

    万大器晚成给定三个list或tuple,大家能够透过for循环来遍历那些list或tuple,这种遍历大家誉为迭代(Iteration卡塔尔国

    alist = [1, 2, 3, 4, 5]
    
    for i in alist:
        print(i)
    
    1
    2
    3
    4
    5
    

    正如将列表中的成分通过for循环,遍历了任何alist列表,这种不重复地惠及当中间的各种子项的表现正是迭代。

     

    1.2 可迭代对象

    可以平昔效果于for循环的指标统称为可迭代对象:Iterable,可迭代对象平常都落到实处了__iter()__办法,可迭代对象通过其内建的方__iter()__重返八个迭代器对象。

    a_iterable = [1, 2, 3]
    
    a_iterator = iter(a_iterable)  # 将可迭代对象转化为迭代器
    
    next(a_iterator)
    
    1
    
    next(a_iterator)
    
    2
    
    next(a_iterator)
    
    3
    

    答案:能够掌握yield是三个生成器;

    1.3 迭代器

    能够被next()函数调用并持续重返下一个值的靶子称为迭代器:Iterator,迭代器其内达成了__iter__方法和__next__主意,for循环本质是经过调用可迭代对象的__iter__方法,该方法重回叁个迭代器对象,再用__next__主意遍历成分

    概念贰个迭代器:

    class MyRange:
        def __init__(self, end):
            self.index = 0
            self.end = end
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.index < self.end:
                val = self.index
                self.index += 1
                return val
            else:
                raise StopIteration()
    
    my_range = MyRange(3)
    
    print([i for i in my_range])
    
    [0, 1, 2]
    
    print([i for i in my_range])
    
    []
    

    迭代器只可以迭代贰回,每一次调用调用 next() 方法就能够上前一步,不能够后退,所以当迭代器迭代到最后时,就不得以另行利用,全体须要将迭代器和可迭代对象分别定义

    改革上边的可迭代对象:

    class MyRange:
        def __init__(self, end):
            self.end = end
    
        def __iter__(self):
            return MyIterator(self.end)
    
    class MyIterator:
        def __init__(self, end):
            self.index = 0
            self.end = end
    
        def __iter__(self):
            return self    
    
        def __next__(self):
            if self.index < self.end:
                val = self.index
                self.index += 1
                return val
            else:
                raise StopIteration()
    
    my_range = MyRange(3)
    
    print([i for i in my_range])
    
    [0, 1, 2]
    
    print([i for i in my_range])
    
    [0, 1, 2]
    

    职能:遭逢yield关键字,函数会直接重回yield值,也就是return;区别的是下一次调用的时候会从yield之后的代码开首试行。

    2. 生成器

    生成器与可迭代对象、迭代器的关联

    图片 1

    图形源于Iterables vs. Iterators vs. Generators

    生成器对象,在每趟调用它的next()方法时回来叁个值,直到它抛出StopInteration。

    生成器是能够迭代的,不过你 只可以够读取它二次,因为它并不把富有的值放在内部存款和储蓄器中,它是实时地扭转数据, 能够用生成器表明式创设:

    my_generator = (x ** 2 for x in range(3))
    
    my_generator
    
    <generator object <genexpr> at 0x7f975b7a4af0>
    
    for i in my_generator:
        print(i)
    
    0
    1
    4
    

    yield

    能够写叁个家常的包蕴yield语句的Python函数,Python会检查测验对yield的行使并将函数标志为一个生成器,当函数执行到yield语句时,像return语句那样重回五个值,不过解释器会保存对栈的援引,它会被用来在下次调用next时上升函数。

    def my_generator():
        yield 1
        yield 2
        yield 'a'
        yield 'generator'
    
    g = my_generator()
    
    g
    
    <generator object my_generator at 0x7f975b7a4d58>
    
    next(g)
    
    1
    
    next(g)
    
    2
    
    next(g)
    
    'a'
    
    next(g)
    
    'generator'
    
    next(g)
    
    ---------------------------------------------------------------------------
    
    StopIteration                             Traceback (most recent call last)
    
    <ipython-input-12-5f315c5de15b> in <module>()
    ----> 1 next(g)
    
    
    StopIteration: 
    

    下面的例证中,每一次调用next()开首实时地转换数据,并赶回,因而生成器只可读取三次,上次实行读取的值在下一次施行中就不能读取。当全部生成器的值都被读取后,在调用机相会世StopIteration的大错特错。

    def my_gen():
        for i in range(5):
            yield i ** 3
    
    my_gen()
    
    <generator object my_gen at 0x7f975ae15a40>
    
    mygen = my_gen()
    
    for i in mygen:
        print(i)
    
    0
    1
    8
    27
    64
    

    历次试行到yield语句,则赶回三个值,再实行的时候从上次停下来的地点开首进行。yield语句保存了上次施行后的情景,后一次实施不是从头开首,而是从上次的场合开头。

    当调用my_gen()那么些函数的时候,函数内部的代码不会立马实践,而是回到三个生成器对象,当使用for循环进行遍历的时候,函数内部的代码开首实行,实行到yield表明式重回二个值,记录当前状态并停止,下一遍的拜见时再从这几个场馆伊始施行。

    举二个不太方便的事例,普通的函数正是从未存档的娱乐,只要游戏发轫,就玩到结尾,下一遍再玩还是从头初阶,而生成器便是加了存档,下一次玩从上次存档的地点初始

     

    有关生成器的思考

    (瞎掰的。。。。卡塔 尔(阿拉伯语:قطر‎生成器到底起到哪些啊功效呢,纵然生成一个生成器对象,而生成器对象自然是二个迭代器,所以能够那样说,生成器重临了两个足以用for循环遍历所以子项,能够用next()方法访问下二个子项,能够在寻访时动态的成形数据而节外省部存款和储蓄器的对象。

    生成器是哪些?

    阅读

    完全知道 Python 迭代对象、迭代器、生成器
    对 Python 迭代的浓烈切磋
    Python迭代器和生成器
    3. (译)Python关键字yield的解释(stackoverflow)
    Python之列表生成式、生成器、可迭代对象与迭代器

    是足以迭代的,不过你 只好够读取它一次 ,因为它并不把具有的值放在内部存款和储蓄器中,它是实时地生成数据:

     

    有人或然会说,小编直接迭代,遍历多好,为啥要用生成器,然后去遍历生成器,这多麻烦。

    那么你要询问,list列表,全数数据是储存在内部存款和储蓄器中的。如果数据量很大,会十一分耗内部存款和储蓄器。

     

     

    yield是几个出奇的return?

    昨今不一致的是实行进度中境遇yield关键字,会阻断,yield 再次来到的是一个生成器。

    先是次迭代中您的函数会进行,从伊始达到 yield 关键字,然后回到 yield 后的值作为第一回迭代的回来值.

    然后,每一趟执行那个函数都会继续施行你在函数内部定义的非常循环的下叁回,再回到那一个值,直到没有能够再次来到的。

     

    只顾,当函数中现身yield,该函数再次来到的正是三个生成器。不在是平时函数。

    def func(num):
        n,a,b = 0,0,1
        while num > n:
            yield b  #阻断,返回b
            a,b = b,a + b
            n+=1
    
    for i in  func(19): #func(19)是一个生成器,生成器只有调用时执行一次。所以这里用循环
        print i
    

     

    而外for循环取值,你也足以经过next()来取下三个值。

    t = func(19)
    t.next()
    

     

    本文由澳门新葡8455最新网站发布于编程教学,转载请注明出处:揭破yield关键字的秘密面纱

    关键词:

上一篇:python队列基本接受

下一篇:没有了