生成器给人的感觉就是用非正常的函数语言定义的迭代器。
任何函数,只要有yield语句,都是迭代器。
例如:
nested_list = [[1,2],[3,4],[5]]
def aGen(nested_list):
for i in nested_list:
for j in i:
yield j
print list(aGen(nested_list))
生成表达式可以更简单的写出迭代器
例如:
gen = ((i+2)*3 for i in xrange(5))#gen是生成器
print gen
print gen.next()
面对nested_list,如果我们不知道对多进行几层循环时,可以使用递归迭代生成器。 例如:
nested_list = [[1,2],[3,4],[5,6,7,8,9],[10,11],12]
def Recur_Gen(nested):
try:
for i in nested:
for j in Recur_Gen(i):
yield j
except TypeError:
yield nested
print list(Recur_Gen(nested_list))
当然,nested_list中的元素都是数字,如果元素师字符串应该如何处理呢?
这时不能直接迭代,会产生无限循环,因为这样会把字符串分解为单个字母,这时可以加号 + 区分字符串和列表
例如:
nested_list = [['aannn','dfdsff'],[3,4],[5,6,7,8,9],[10,11],12]
def Recur_Gen(nested):
try:
try:
nested + ''
except TypeError:
pass
else:
raise TypeError
for i in nested:
for j in Recur_Gen(i):
yield j
except TypeError:
yield nested
print list(Recur_Gen(nested_list))
在生成器运行过程中,可以利用send与生成器函数内部联系。 例如:
def aGentoRepeat(value):
while True:
new = (yield value) #the enterance
if new is not None:
value = new
g = aGentoRepeat(12)
print g.next() # result is: 12
print g.send("oh hi") #result is: oh hi
当然,生成器还有两个函数 throw 和 close The throw method (called with an exception type, an optional value and traceback object) is used to raise an exception inside the generator (at the yield expression).
The close method (called with no arguments) is used to stop the generator.
close函数会引起GeneratorExit报错,终止生成器。当然,也可以直接raise GeneratorExit.
在老版本的Python中没有生成器,但是人们有模拟生成器的方法。
例如:
def gen(nested):
result = []
try:
try:
nested + ''
except TypeError:
pass
else: raise TypeError
for sublist in nested:
for element in gen(sublist):
result.append(element)
except TypeError:
result.append(nested)
return result