重复做多次事情
#裴波那契数列,每个数是前两个数的和
class Fibs():
    def __init__(self):
        self.a = 0
        self.b = 1
    def next(self):            #返回迭代器的下一个值
        self.a, self.b = self.b, self.a + self.b
        return self.a
    def __iter__(self):             #迭代,返回self
        return self
fibs = Fibs()
for f in fibs:
    if f > 1000:
        print f
        break
#可以通过iter函数从可迭代的对象获取迭代器
it = iter([1,3,7])
it.next()
it.next()
it.next()
it.next()         #已经没有值可以返回了
#从迭代器获得序列
class Fibs():
    def __init__(self):
        self.a = 0
        self.b = 1
    def next(self):
        self.a, self.b = self.b, self.a + self.b
        if self.a > 1000:                       #构造一个1000以内的裴波那契序列
            raise StopIteration             #序列元素必须是有穷的,引发异常StopIteration即可终止迭代
        else:
            return self.a
    def __iter__(self):
        return self
fib = Fibs()      #获取一个迭代器
list(fib)       #通过list函数显示地把迭代器构造为列表
任何包含yield语句的函数都叫生成器
yield语句产生一个值,并且使函数暂停,等待下一次唤醒(再次调用)  
nested = [[1,2], [3,4], [5]]
def flatten(nested):
    for sublist in nested:       #迭代列表中的列表
        for element in sublist:        #迭代最里层的元素
            yield element        #产生一个element值并且暂停,等到下一次唤醒会从原处继续执行
for num in flatten(nested):      #把生成器拿来迭代使用
    print num
#把生成器转换为列表 
list(flatten(nested))
列表推导式可以得到一个列表(一次性列出)
生成器推导式可以得到一个生成器(一个一个列出)
两者的关系类似与range()和xrange()的关系
g = ( (x, y, x * y) for x in range(1,9) for y in range(1, 9) )      #产生一个生成九九乘法表的生成器
g.next()       #和迭代器一样,有next方法
g.next()
#生成器推导式不一定要有独立的圆括号括起来,只要两边是圆括号,即使不是自己的,也能实现
sum(i ** 2 for i in range(10))      #这里两边的括号是属性求和函数sum的
                                                      #这里表示求10以内的平方和
nested = [[1,2,3],4,[ [5,6],7 ],8]        #有任意层嵌套的列表
def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):     #嵌套
                yield element
    except TypeError:          #最里层的递归在执行第三行时,nested参数已经是元素,不可迭代
        yield nested
#字符串等对象(字符串、Unicode、UserString等)不适合迭代,此处无法处理字符串等对象
list( flatten(nested) )
#因为字符串等对象不适合迭代,所以我们应当加入一段检查语句
def flatten(nested):
    try:
        #检查是否为字符串等对象
        try:
            nested + ''        #尝试字符串连接
        except TypeError:
            pass
        else:
            raise TypeError            #如果成功连接了,说明nested是类似字符串的对象,引起TypeError,跳转到最后一行直接生成字符串
        
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested
list( flatten(['aaaa', 'bbbb', [1,2,3], [[4,5],6],7]) )
生成器包括两个部分——生成器的函数 和 生成器的迭代器
def simple_generator():
    yield 1
simple_generator        #生成器的函数
simple_generator()           #生成器的迭代器
def repeater(value):
    while True:
        new = (yield value)    #yield表达式,两边最好有圆括号
        if new is not None: value = new            #如果new取到的不是空值,拿就把它赋给value方便下一次调用
r = repeater(42)
r.next()
r.next()
r.send('Hello world!')
旧版python并不能使用生成器,但我们可以模拟出大部分的生成器(只能有穷)
#改写flatten
def flatten(nested):
    result = []           #把这个列表作为迭代器
    try:
        try:
            nested + ''
        except TypeError:
            pass
        else:
            raise TypeError 
        
        for sublist in nested:
            for element in flatten(sublist):
                result.append(element)              #给result追加元素取代yield语句
    except TypeError:
        result.append(nested)               #取代yield语句
    return result          #把列表作为结果返回