澳门至尊网站-首页

您的位置:澳门至尊网站 > 技术教程 > 揭开yield关键字的神秘面纱

揭开yield关键字的神秘面纱

2019-10-16 15:29

写在前言

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()

 

本文由澳门至尊网站发布于技术教程,转载请注明出处:揭开yield关键字的神秘面纱

关键词: