2-2-11 函数-生成器yield
生成器是由函数+yield关键字创造出来的写法,在特定情况下,用他可以帮助我们节省内存。
-
生成器函数,但函数中有yield存在时,这个函数就是生产生成器函数。
def func(): print(111) yield 1
def func(): print(111) yield 1 print(222) yield 2 print(333) yield 3 print(444)
-
生成器对象,执行生成器函数时,会返回一个生成器对象。
def func(): print(111) yield 1 print(222) yield 2 print(333) yield 3 print(444) data = func() # 执行生成器函数func,返回的生成器对象。 # 注意:执行生成器函数时,函数内部代码不会执行。
def func(): print(111) yield 1 print(222) yield 2 print(333) yield 3 print(444) data = func() v1 = next(data) print(v1) v2 = next(data) print(v2) v3 = next(data) print(v3) v4 = next(data) print(v4) # 结束或中途遇到return,程序爆:StopIteration 错误
data = func() for item in data: print(item)
生成器的特点是,记录在函数中的执行位置,下次执行next时,会从上一次的位置基础上再继续向下执行。
应用场景
-
假设要让你生成 300w个随机的4位数,并打印出来。
- 在内存中一次性创建300w个
- 动态创建,用一个创建一个。
import random val = random.randint(1000, 9999) print(val)
import random data_list = [] for i in range(300000000): val = random.randint(1000, 9999) data_list.append(val) # 再使用时,去 data_list 中获取即可。 # ...
import random def gen_random_num(max_count): counter = 0 while counter < max_count: yield random.randint(1000, 9999) counter += 1 data_list = gen_random_num(3000000) # 再使用时,去 data_list 中获取即可。
-
假设让你从某个数据源中获取300w条数据(后期学习操作MySQL 或 Redis等数据源再操作,了解思想即可)。
所以,当以后需要我们在内存中创建很多数据时,可以想着用基于生成器来实现一点一点生成(用一点生产一点),以节省内存的开销。
扩展1
def func():
print(111)
v1 = yield 1
print(v1)
print(222)
v2 = yield 2
print(v2)
print(333)
v3 = yield 3
print(v3)
print(444)
data = func()
n1 = data.send(None)
print(n1)
n2 = data.send(666)
print(n2)
n3 = data.send(777)
print(n3)
n4 = data.send(888)
print(n4)
作业:
'''
请编写一个生成器函数实现生成n个斐波那契数列的值。
- 什么是斐波那契数列?
前两个数相加的结果,就是下一个数。
1 1 2 3 5 8 13 21 34 55 ...
- 代码结构示例,请在此基础上补充代码实现。
'''
def fib(max_count):
first = 1
second = 0
count = 0
while count < max_count:
next_value = first + second
first = second
second = next_value
yield next_value
count += 1
count = input("请输入要生成斐波那契数列的个数:")
count = int(count)
fib_generator = fib(count)
for num in fib_generator:
print(num)
扩展2 yield from
执行时可以调用另外一个函数中并执行,执行完了返回到原来函数继续执行
def foo():
yield 2
yield 2
yield 2
def func():
yield 1
yield 1
yield 1
yield from foo()
yield 1
yield 1
for item in func():
print(item)