生成器是一种特殊的迭代器,应该说更高级,它也是用于节省内存。
生成器是包含yield的函数,就这么简单。
它的特点是:在函数运行过程中,如果遇到yield,会暂停,并且返回一个值,等到下次执行时,从上次停止的地方开始
生成器写法
def counter(start_at=0): count=start_at while True: print(1) yield count # 通过yield返回 print(2) if count>10: raise StopIteration else: count+=1 c=counter() print c.next() # 可以看到第一次next停在了yield处,并且返回了count,没有打印2 # 1 # 0 for _ in range(2): print('next:', c.next()) # 可以看到下次执行从yield后开始,先打印2,然后while训练 # 2 # 1 # ('next:', 1) # 2 # 1 # ('next:', 2)
注意 yield count的写法,后面会有不同
交互的生成器
def counter(start_at=0): count=start_at while True: count=(yield count) # 通过yield获得了某个值 赋给 count print(count,'count') if count>10: raise StopIteration else: count+=1 c=counter() print(c.next()) # 0 print c.send(5) #(5, 'count') yield通过send获得5,赋给count # 6 send的同时也执行了next方法
1. send 信息给生成器
2. count = (yield count) 接收send的信息时必须这么写
3. 在send时自动执行了next
def counter(start_at=0): count=start_at while True: val=(yield count) if val is not None: count=val else: count+=1 count=counter(5) print count.next() # 5 print count.next() # 6 此时没有send,相当于send了一个None,所以count+1 print count.send(9) # 9 此时send了9,val不是None,所以count=val print count.next() # 10 count.close()
结束时也会报StopIteration
生成器表达式
和列表解析式很相似,区别在于列表解析时是一次性对所有元素进行了处理,而生成器表达式和生成器一样,是一个一个处理。
import time def func(x): return x*2^4 a = range(100) time.clock() # [func(i) for i in a] # 5.97484334364e-05 (func(i) for i in a) # 5.49832209537e-06 print(time.clock())
可以看到生成器表达式比列表解析快了将近10倍,因为他只处理了第一个元素。