生成器是一种特殊的迭代器,应该说更高级,它也是用于节省内存。

 

生成器是包含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倍,因为他只处理了第一个元素。