第一次看到Python代码中出现yield关键字时,一脸懵逼,完全理解不了这个。网上查下解释,函数中出现了yield关键字,则调用该函数时会返回一个生成器。那到底什么是生成器呢?我们经常看到类似下面的代码
def count(n):
x = 0
while x < n:
yield x
x += 1
for i in count(5):
print i
这段代码执行后打印序列0到4,所以我一开始以为这个生成器就是生成一个序列呀。那这跟迭代器有什么区别呢?我们来看下迭代器的例子:
class CountIter:
def __init__(self, n):
self.n = n
def __iter__(self):
self.x = -1
return self
def next(self): # For Python 2.x
self.x += 1
if self.x < self.n:
return self.x
else:
raise StopIteration
for i in CountIter(5):
print i
CountIter类就是一个迭代器,它的__iter__()方法返回可迭代对象,next()方法则执行下一轮迭代(注:在Python 3.x里是__next__()方法)。上面的代码执行后也会打印序列0到4,看上去跟之前的生成器效果一样,就是代码长一点。不仅如此,生成器自带next()方法,而且在越界时也会抛出StopIteration异常。
close()方法
顾名思义,close()方法就是关闭生成器。生成器被关闭后,再次调用next()方法,不管能否遇到yield关键字,都会立即抛出StopIteration异常。
gen = (x for x in range(5))
gen.close()
gen.next() # StopIteration
send()方法
这是我认为生成器最重要的功能,我们可以通过send()方法,向生成器内部传递参数。我们来看个例子:
def count(n):
x = 0
while x < n:
value = yield x
if value is not None:
print 'Received value: %s' %value
x += 1
还是之前的count函数,唯一的区别是我们将”yield x”的值赋给了变量value,并将其打印出来。如何给value传值呢?
gen = count(5)
print gen.next() # print 0
print gen.send('Hello') # Received value: Hello, then print 1
我们先调用next()方法,让代码执行到yield关键字(这步必须要),当前打印出0。然后当我们调用”gen.send(‘Hello’)”时,字符串’Hello’就被传入生成器中,并作为yield关键字的执行结果赋给变量”value”,所以控制台会打印出”Received value: Hello”。然后代码继续执行,直到下一次遇到yield关键字后暂定,此时生成器返回的是1。