首页 > 代码库 > python高级编程之迭代器与生成器

python高级编程之迭代器与生成器

# -*- coding: utf-8 -*-

# python:2.x

__author__ = ‘Administrator‘

#迭代器与生成器

#---------------------------------------

#迭代器基于2个方法

"""

next:返回容器下一个项目

__iter__:返回迭代器本身

"""

#通过内建函数和序列来创建

i=iter(‘abc‘)

print i.next()#a

print i.next()#b

print i.next()#c

#print i.next()异常StopIteration

#当序列遍历完之后,出现StopIteration异常,与循环进行兼容,可以通过 使用next方法类来得到结果

class Miter(object):

    def __init__(self,a):

        self.a=a

    def next(self):

        if self.a==0:

            raise  StopIteration

        self.a-=1

        return self.a

    def __iter__(self):

        return self

for el in Miter(4):

    print el

 

#注意:迭代器是底层特性和概念,一般情况下,程序代码中可以没有它们

#------------------------------

#生成器

#特点是:简单,高效,基于yield指令,可以暂停一个函数并返回中间结果,必须是可以恢复

def fib():

    a,b=0,1

    while True:

        yield b

        a,b=b,a+b

 

f=fib()

print f.next()#1

print f.next()#1

print f.next()#2

print [f.next() for i  in range(10)]#返回特殊的迭代器,也就是generator对象,请看:http://www.cnblogs.com/itech/archive/2011/01/19/1939119.html

#重点:当需要一个将返回一个序列或者在循环中执行的函数时,就考虑生成器

 

import tokenize

#官方文档:https://docs.python.org/2/library/tokenize.html

reader=open(‘a1.py‘,‘r‘).next

tokens=tokenize.generate_tokens(reader)

print tokens.next()#(53, ‘# -*- coding: cp936 -*-‘, (1, 0), (1, 23), ‘# -*- coding: cp936 -*-\n‘)

#注意:因为没有高级编程上面那个文件,所以只能使用自己的文件

print tokens.next()#(54, ‘\n‘, (1, 23), (1, 24), ‘# -*- coding: cp936 -*-\n‘)

print tokens.next()#(1, ‘def‘, (2, 0), (2, 3), ‘def a(a1):\n‘)

print tokens.next()#(1, ‘a‘, (2, 4), (2, 5), ‘def a(a1):\n‘)

"""

open()函数进行遍历了文件中每一行,generate_tokens()则在一个管道中对其进行遍历,完成一些额外的工作

"""

#例子:说明函数用来在序列上面定义一个转换,然后被链接起来应用 ,每次调用将处理一个元素,并返回它的结果

def power(values):

    for values2 in values:

        print values2

        yield  values2

 

def addr(values):

    for value in values:

        print value

        if value%2==0:

            yield  value+3

        else:

            yield  value+2

 

el=[1,4,7,9,12,19]

res=addr(power(el))

print res.next()#1,1,3

 

#注意

"""

保持代码简单,而不是数据{

拥有许多简单的处理序列值的可迭代函数,要比一个复杂的,每次计算一个值的函数更好一些}

"""

#python引入的与生成器最后一个特性是提供了与next()方法调用的代码交互功能,yield变成一个表达式,而一个值 可以通过名为send新方法来传递

def psy():

    print ‘pleass tell me your problems‘

    while True:

        anwer=(yield)

        if anwer.endswith(‘?‘):

            print ("don‘t ask your self")

        elif ‘good‘ in anwer:

            print ‘good gon‘

        elif ‘bad‘ in anwer:

            print ‘bad‘

Pay=psy()

Pay.next()#pleass tell me your problems

Pay.send(‘i fell bad‘)#bad

Pay.send(‘why i shou ?‘)#don‘t ask your self

#原理

"""

send的工作机制与next一样,但需要yield将变成能够返回传说的值,同时还有throw和close函数

throw允许客户端代码传入要招聘的任何类型的异常

close的工作方式是相同的,但是将会招聘一个特定的异常<GeneartorExit>,在这样的情况下,生成器函数必须再次GeneartorExit

或者StopIteration异常

"""

#典型生成器模板

def My_GeneartorExit():

    try:

        yield ‘something‘

    except ValueError:

        yield ‘dealing with the exception‘

    finally:

        print ‘ok clean‘

my=My_GeneartorExit()

print my.next()#ok clean和something

print my.throw(ValueError(‘mean mean mean‘))#dealing with the exception

my.close()#ok clean

#print my.next()StopIteration

#说明

"""

finally在之前版本是不允许使用的,它将捕获任何未被捕获的close和throw调用,是完成清理工作的推荐方式,

GeneartorExit异常在生成器中是无法被捕获的,因为它被编译器用来确定调用close时是否正常退出,如果有代码与这个异常关联,那么解释程序将抛出一个系统错误

并退出

"""