python中的生成器generator

来源:互联网 发布:mac 命令行上传文件 编辑:程序博客网 时间:2024/05/17 06:23

生成器的一个特点是,它是延时的操作,可以在需要的时候产出结果,而不是立即产生结果。而且,生成器也是一个迭代器。生成器也是单向有序地遍历,所以它只能遍历一次。

两种方式来构造生成器:

1.生成器函数:和普通函数一致,只不过是把return替换为yield,yield类似于next()函数,使用一次产出一个结果。然而,yield产出的结果并不是像next()一样立即打印出来,而是自动挂起并暂停执行。当yield被调用的时候,返回一个生成器对象,这个对象支持迭代器接口。

比如:

>>> def generator(n):
    for i in range(10):
        yield i+1

       
>>> for i in generator(4):
    print i,":",

   
1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 :

yield所在的函数返回的生成器对象支持迭代器接口:

>>> g=generator(3)
>>> g.next()
1
>>> g.next()
2
>>> g.next()
3
>>> g.next()
4

…………

StopIteration

 

2.通过列表来提供生成器:

>>> b=[x+1 for x in range(5)]
>>> b
[1, 2, 3, 4, 5]

>>> for i in b:
    print i,":",

   
1 : 2 : 3 : 4 : 5 :

yield后面可以带数值,生成器函数内可以使用send()函数,这样我们就可以忽略掉中间那些输出,指定插入我们想要输出的内容:

>>> def g(a):
    print "hello"
    b=yield a
    print b
    d=yield 'hi'
    e=yield 1
    print "end"

   
>>> c=g("world")
>>> c.next()
hello
'world'
>>> c.send('jack')
jack
'hi'
>>> c.next()
1

>>> c.next()
end

Traceback (most recent call last):
  File "<pyshell#88>", line 1, in <module>
    c.next()
StopIteration

 

send()中断next():

def g(x):
    while 1:
        val=yield x
        if val is not None:
            x=val
        else:
            x+=1

>>> d=g(3)
>>> print d.next()
3
>>> print d.next()
4

>>> print d.send(100)
100
>>> print d.next()
101

当我们需要中断生成器,可以定义一个函数,通过throw抛出GeneratorExit异常:

def close(self):
    try:
        self.throw(GeneratorExit)
    except(GeneratorExit,StopIteration):
        print 'that is all'

还是前面的例子

>>> c=g('world')
>>> c.next()
hello
'world'
>>> close(c)
that is all
假如再次使用next():

>>> c.next()

Traceback (most recent call last):
  File "<pyshell#129>", line 1, in <module>
    c.next()
StopIteration

 

总结一下生成器:

实际上生成器就是一个迭代器,支持迭代器接口,可以用next()函数;语法上和普通函数类似,只是把return换成yield(带yiled的函数会被视为一个生成器);每执行一次yield,都会挂起生成器状态,需要时可以从挂起时位置调用

 

生成器有什么优点?

可以简化代码,使得代码行数更少,而且更易理解。生成器函数每次调用yield,都会产生一次中断,返回一个当前迭代值,函数内调用了多少次yield就相当于中断了多少次。打个比喻,使用普通函数时好比一边拨花生壳吃花生米,重复这样的循环,使用生成器的时候好比是你把花生都拨完壳,然后你可以想要什么时候吃就什么时候吃你的花生米

举例,斐波那契数列实现:

(1):                                                              (2):

>>> def fa(max):
    n,a,b=0,0,1
    L=[]
    while n<max:
        L.append(b)
        a,b=b,a+b
        n+=1
    return L

>>> for n in fa(5):
    print n

   
1
1
2
3
5

>>> def fab(max):
    n,a,b=0,0,1
    while n<max:
        yield b
        a,b=b,a+b
        n+=1

       
>>> for n in fab(5):
    print n

   
1
1
2
3
5

0 0
原创粉丝点击