Python生成器代器,和迭代器

generator


生成器generator:壹边循环一边图谋的编写制定。

生成器是三个奇特的次序,能够被用于调节循环的迭代行为。python中的生成器是迭代器的壹种,使用yield重临值函数,每一回调用yield会暂停,能够利用next()函数和send()函数恢复生机生成器。

生成器类似于再次来到值为数组的三个函数,那个函数尚可参数,能够被调用。不过,区别于一般函数会3回性重临包涵了颇具数值的数组,生成器3遍只可以发出2个值,这么些消耗的内部存款和储蓄器数量将大大缩减。因而,生成器看起来像是三个函数,可是表现得像迭代器。

一.第3种方式,只要把2个列表生成式的[]改成()

Python的迭代器和生成器,Python代器生成器

先说迭代器,对于string、list、dict、tuple等那类容器对象,使用for循环遍历是很便宜的。在后台for语句对容器对象调用iter()函数,iter()是python的停放函数。iter()会回去三个概念了next()方法的迭代器对象,它在容器中每一种访问容器内元素,next()也是python的内置函数。在尚未承继成分时,next()会抛出一个StopIteration格外,文告for语句循环停止。举例:

>>> s = 'abc'
>>> it = iter(s)
>>> it
<str_iterator object at 0x7f71fefe9d68>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration

上边说的都是python自带的容器对象,它们都落到实处了对应的迭代器方法,那假如是自定义类需求遍历如何做?方法很简短,对这一个类AClass,达成多个__iter__(self)方法,使其回来一个涵盖__next__(self)方法的指标就能够了。假如你在AClass刚好也定义了__Python生成器代器,和迭代器。next__(self)方法(一般选取迭代器都会定义),那在__iter__里假使回到self就能够。废话少说,先上代码:

class Fib(object):
  def __init__(self, max):
    super(Fib, self).__init__()
    self.max = max

  def __iter__(self):
    self.a = 0
    self.b = 1
    return self

  def __next__(self):
    fib = self.a
    if fib > self.max:
      raise StopIteration
    self.a, self.b = self.b, self.a + self.b
    return fib

def main():
  fib = Fib(100)
  for i in fib:
    print(i)

if __name__ == '__main__':
  main()

一句话来讲讲下代码会干什么,定义了一个Fib类,用于生成fibonacci连串。用for遍历时会相继打印生成的fibonacci数,max是浮动的fibonacci系列中数字大小的上限。

在类的贯彻中,定义了1个__iter__(self)方法,这么些艺术是在遍历时被iter()调用,重返多个迭代器。因为在遍历的时候,是从来调用的python内置函数iter(),由iter()通过调用__iter__(self)获得对象的迭代器。有了迭代器,就足以每一个遍历成分了。而种种遍历的时候,也是使用内置的next()函数通过调用对象的__next__(self)方法对迭代器对象开始展览遍历。所以要达成__iter__(self)和__next__(self)。而且因为达成了__next__(self),所以在落到实处__iter__(self)的时候,直接回到self就足以。

为了越来越好领悟,小编再不难重复下方面说的那一段:在循环遍历自定义容器对象时,会动用python内置函数iter()调用遍历对象的__iter__(self)获得三个迭代器,之后再循环对那一个迭代器使用next()调用迭代器对象的__next__(self)。__iter__只会被调用3遍,而__next__会被调用
n 次。

上边说生成器。

生成器(Generator)是创办迭代器的简练而庞大的工具。它们写起来就像正规的函数,只是在需求回到数据的时候利用yield语句。每一遍next()被调用时,生成器会回去它退出的职分(它回想语句最终二回施行的任务和全部的数据值)。以下示例演示了生成器能够很简单的成立出来:

>>> def reverse(data):
...   for index in range(len(data)-1, -1, -1):
...     yield data[index]
... 
>>> for char in reverse('hello'):
...   print(char)
... 
o
l
l
e
h

有关迭代器和生成器的差距,生成器能成功迭代器能做的全体事,而且因为电动创造了__iter__()和
next()方法,生成器显得非常简洁,而且生成器也是高速的。除了成立和封存程序状态的全自动格局,当发生器终结时,还会自行抛出StopIteration极度。一个带有yield的函数就是二个生成器,它和普通函数差异,生成一个 generator
看起来像函数调用,但不会试行其余函数代码,直到对其调用next()(在 for
循环中会自动调用next())才起来试行。纵然施行流程仍按函数的流水生产线施行,但每推行到二个yield语句就能暂停,并赶回一个迭代值,下一次推行时从yield的下1个口舌继续实践。看起来就象是多个函数在正规实施的经过中被yield中断了数10回,每一次中断都会经过yield再次来到当前的迭代值(yield暂停多个函数,next()从其暂停处还原其运行)。

其余对于生成器,python还提供了多个生成器表明式:类似与贰个yield值的无名氏函数。表达式本人看起来像列表推到,
但不是用方括号而是用圆括号包围起来:

>>> unique_characters = {'E', 'D', 'M', 'O', 'N', 'S', 'R', 'Y'}
>>> gen = (ord(c) for c in unique_characters)
>>> gen
<generator object <genexpr> at 0x7f2be4668678>
>>> for i in gen:
...   print(i)
... 
69
79
83
77
82
78
89
68
>>> 

如若要求,能够将生成器表明式传给tuple、list或是set来迭代全部的值并且再次回到元组、列表或是群集。在这种状态下,无需1对额外的括号
———— 直接将生成器表明式 ord(c) for c in
unique_characters传给tuple()等函数就足以了, Python
会推测出它是贰个生成器表明式。

提起底,为啥要使用生成器?因为效能。使用生成器表达式代替列表深入分析能够而且节约
cpu 和 内部存款和储蓄器(ram)。就算您构造3个列表的指标只有是传递给别的函数,(举例传递给tuple()也许set()), 那就用生成器表达式代替吧!

上述所述正是本文的全部内容了,希望大家能够喜欢。

先说迭代器,对于string、list、dict、tuple等那类容器对象,使用for循环遍历是很便利的。在后台f…

Python生成器和迭代器,Python生成器代器

创建generator

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

 1、生成器

 通过列表生成式,我们得以直接成立1个列表。可是,受到内部存款和储蓄器的限定,列表体量断定是零星的。而且,创造1个涵盖十0万个成分的列表,不唯有占用相当的大的仓库储存空间,借使大家1味访问后面多少个要素,那背后绝大成分占用的空间都白白浪费。所以,固然列表成分得以依照某种算法推算出来,那大家是不是足以在循环的历程中不停推算出后续的成分?那样就不必须创建完整的list,从而省去多量的空间。在Python中,那样1方面循环一边图谋的建制,称为生成器:generator。

 

要创制二个generator有很三种格局。第三个章程非常粗大略,只要把1个列表的[]改为(),就创办了一个generator:

>>> L = [x*x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x7fafe19d2410>

要是要一个2个打字与印刷出生成器的成分,能够透过next()函数拿到:

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

每一趟调用next(),就总结出g的下二个要素,知道总计到最终一个成分,未有更加的多成分,就能报错。

#!/usr/bin/env python

g = (x*x for x in range(10))
for n in g:
    print(n)

====================================
0
1
4
9
16
25
36
49
64
81

从而常常都以用for循环来迭代它。

裴波拉切数列用列表生成式写不出去,不过用函数可以:上边包车型客车函数和generato仅一步之遥

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'

留神赋值语句:

a, b = b, a + b

相当于:

t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]

上面的函数和generato仅一步之遥,只需要把print(b)改为yield b就可以了

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'

图片 1

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图