一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
def generator():
print(1)
return 'a'
ret = generator()
print(ret)
只要含有yield关键字的函数都是生成器函数。
1)yield只能写在函数里;
2)yield不能跟return共用;
def generator():
print(1)
yield 'a'
ret = generator()
print(ret)
结果:
生成器函数:执行之后会得到一个生成器对象作为返回值。
def generator():
print(1)
yield 'a'
ret = generator()
print(ret)
print(ret.__next__())
结果:
再看:
def generator():
print(1)
yield 'a'
print(2)
yield 'b'
g = generator()
print(g)
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
结果:
如果再加ret = g.__next__() print(ret)代码,就会发生溢出。会出现迭代器取不到的时候,有stopIteration的错误提示。
我们可以看到函数内部的执行,是受外部控制的。通过yield和__next__两者来对函数进行控制。
def generator():
print(1)
yield 'a'
print(2)
yield 'b'
g = generator()
for i in g:
print(i)
既然有__iter__和__next__,那么我们可以使用for循环来管理。
那我们现在看例子:
def hello():
for i in range(2000000):
yield 'hello %s' % i
g = hello()
for i in g:
print(i)
背后的原理是:这边生产一个,然后就给你一个打印,边生产边打印,这样就不会一下子在内存中产生大量的数据。不是一次性将所有的数据都生成出来,然后再提供给你。这样,就需要大量的内存空间。数据越存越多,越到后面,程序需要去找内存,非常麻烦。
如果只想打印50个:
def hello():
for i in range(2000000):
yield 'hello %s' % i
g = hello()
count = 0
for i in g:
count += 1
print(i)
if count > 50:
break
# print(g.__next__())
for i in g:
count += 1
print(i)
if count > 100:
break
这个应该有一个位置记录,迭代的过程中记录下一个位置。下一个for循环就从下一个位置开始获取值。
l = [1, 2, 3, 4, 5]
for i in l:
print(i)
if i == 2:
break
for i in l:
print(i)
这个例子里说for循环,是生成了一个迭代器。然后for循环结束之后,第二个for循环,迭代器又从头开始执行。
看一个工厂生产衣服的例子:
def produce():
"""生产衣服"""
for i in range(2000000):
yield "生产了第%s件衣服"%i
product_g = produce()
print(product_g.__next__()) #要一件衣服
print(product_g.__next__()) #再要一件衣服
print(product_g.__next__()) #再要一件衣服
num = 0
for i in product_g: #要一批衣服,比如5件
print(i)
num +=1
if num == 5:
break
#到这里我们找工厂拿了8件衣服,我一共让我的生产函数(也就是produce生成器函数)生产2000000件衣服。
#剩下的还有很多衣服,我们可以一直拿,也可以放着等想拿的时候再拿
一个函数可以监听文件的输入:
def tail(filename):
f = open(filename, encoding='utf-8')
while True:
line = f.readline()
if line.strip():
yield line.rstrip()
g = tail('log')
for i in g:
if 'python' in i:
print('hello', i)