python生成器

2019-12-06 09:44栏目:编程学习

写在序言

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(卡塔尔(英语:State of Qatar)函数调用并不唯有重返下一个值的靶子称为迭代器: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(卡塔尔(英语:State of Qatar)方法就能够上前一步,无法后退,所以当迭代器迭代到最终时,就不得以重新利用,全部须要将迭代器和可迭代对象分别定义

改善上面包车型大巴可迭代对象:

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(卡塔尔(英语:State of Qatar)开端实时地变化数据,并再次来到,由此生成器只可读取二次,上次实行读取的值在下一次实践中就无法读取。当整个生成器的值都被读取后,在调用机缘现身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(卡塔尔(英语:State of Qatar)这么些函数的时候,函数内部的代码不会登时举办,而是再次回到叁个生成器对象,当使用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()

 

版权声明:本文由威尼斯人app发布于编程学习,转载请注明出处:python生成器