重复做多次事情
#裴波那契数列,每个数是前两个数的和
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 #把列表作为结果返回