生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值。
生成器可以通过生成器表达式和生成器函数获取到
生成器表达式
创建生成器对象和创建列表生成式特别像
# 创建列表生成式 >>> list_num = [x for x in range(10)] >>> list_num [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 生成器 >>> glist_num = (x for x in range(10)) # 只需要把中括号换成小括号就成了生成器 >>> glist_num <generator object <genexpr> at 0x7fc3d7375830> >>> glist_num.__next__() 0 >>> glist_num.__next__() 1 >>> next(glist_num) 2 >>> next(glist_num) 3 # 生成器表达式内部的代码只有在迭代取值的时候才会执行
使用next()
和使用__next__()
一样
生成器函数
生成器函数指的是函数体中包含yield
关键字的函数
定义生成器函数和定义普通函数一样。
# 1 生成器函数 >>> def my_func(): print("Hello") yield >>> my_func() <generator object my_func at 0x7fc3d6c70e08> >>> res = my_func() >>> res <generator object my_func at 0x7fc3d6c70e60> >>> next(res) Hello >>> >>> next(res) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration # 生成器函数(yield有返回值) def my_func(): print("Hello") yield 1 res = my_func() r = res.__next__() # 会执行 print("Hello") print(r) # r为yield的返回值 # 执行结果: Hello 1 # 生成器函数(yield多个返回值) def my_func(): print("Hello") yield 1,2 res = my_func() r = res.__next__() print(r) # 执行结果: Hello (1, 2) #函数中只有一个yield所以只能执行一次__next__()方法 def my_func(): print("Hello") yield 1,2 res = my_func() print(res.__next__()) print(res.__next__()) # 调用两次就会报错 #执行结果: Hello (1, 2) Traceback (most recent call last): File "b.py", line 8, in <module> print(res.__next__()) StopIteration # 有多个yield def my_func(): print("Hello") yield 1,2 print("world") yield 'a','b' res = my_func() print(res.__next__()) # 每执行一个__next__代码往下运行到yield停止 返回后面的数据 print(res.__next__()) # 每执行一个__next__代码往下运行到yield停止 返回后面的数据
注意:当函数体内含有yield
关键字 那么在第一次调用函数的时候,并不会执行函数体代码,而是将函数变成了生成器(迭代器).
每执行一个__next__
代码往下运行到yield停止 返回后面的数据.
yield
不但能返回值,而且还能给它传值
yield
传值
使用send
给yield
传值
示例:
def my_define(name): print("%s is doing work" % name) while True: play = yield print("%s is do %s" %(name, play)) res = my_define("Hans") res.__next__() res.__next__() # 执行结果: Hans is doing work Hans is doing None # 给yield传值: def my_define(name): print("%s is doing work" % name) while True: play = yield print("%s is do %s" %(name, play)) res = my_define("Hans") res.__next__() res.__next__() # 给yield传两个值:write和coding res.send("write") res.send("coding") # 执行结果: Hans is doing work Hans is do None Hans is do write Hans is do coding
模拟range功能
# 代码 def my_range(start, stop=None, step = 1): if not stop: stop = start start = 0 while start < stop: yield start start += step print("一个参数") for i in my_range(3): print(i) print("两个参数") for i in my_range(1,3): print(i) print("三个参数") for i in my_range(1, 10, 2): print(i) # 执行结果: 一个参数 0 1 2 两个参数 1 2 三个参数 1 3 5 7 9
求和(面试题)
# 代码: def add(n, i): return n + i def test(): for i in range(4): yield i g = test() for n in [1, 10]: g = (add(n, i) for i in g) res = list(g) print(res) #从下面的结果中选择一个: #A. res=[10,11,12,13] #B. res=[11,12,13,14] #C. res=[20,21,22,23] #D. res=[21,22,23,24] # 解析: def add(n, i): return n + i # 调用之前是函数 调用之后是生成器 def test(): for i in range(4): yield i g = test() # 初始化生成器对象 for n in [1, 10]: g = (add(n, i) for i in g) """ 第一次for循环 g = (add(n, i) for i in g) 第二次for循环 g = (add(10, i) for i in (add(10, i) for i in g)) """ res = list(g) print(res) #执行结果为:[20,21,22,23], 答案选C #A. res=[10,11,12,13] #B. res=[11,12,13,14] #C. res=[20,21,22,23] #D. res=[21,22,23,24]
yield
return
迭代器对象 生成器对象 我们都可以看成是"工厂",只有当我们所要数据的时候工厂才会加工出"数据"
主要目的就是节省空间
内置函数
https://docs.python.org/zh-cn/3/library/functions.html