迭代器和生成器
1、生成器与yield
1.1 创建生成器的第一种方式
如果函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值也就是生成器对象
def my_range(start, stop, step=1): print('start...') while start < stop: yield start start += step print('end...') g = my_range(0, 5) print(g)
输出结果:
<generator object my_range at 0x000002549A231E00>
1.2 生成器的本质就是一个迭代器
生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器
def my_range(start, stop, step=1): print('start...') while start < stop: yield start start += step print('end...') g = my_range(0, 5) print(g.__next__()) # 触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数 print(g.__next__()) # 再次调用,函数从上次暂停的位置继续执行,直到遇到新的yield print(g.__next__()) print(g.__next__()) print(g.__next__()) print(g.__next__()) # 触发函数执行没有遇到yield则没有值返回,即取值完毕抛出异常结束迭代
输出:
Traceback (most recent call last): File "D:\python\基础\迭代.py", line 15, in <module> print(g.__next__()) StopIteration start... 0 1 2 3 4 end... Process finished with exit code 1
2、yield表达式应用
def eater(): print('ready to eat...') while True: food = yield print(f'eat the food {food} and start to eat ...') g = eater() # 得到生成器对象 g.__next__() # 初始化,让函数挂起在food = yield ,等待调用g.send()方法传值 g.send('food1') g.send('food2')
输出:
ready to eat... eat the food food1 and start to eat ... eat the food food2 and start to eat ...
表达式形式的yield也可以用于返回多次值,即变量名 = yield 值的形式,如下代码
def eater(): print('ready to eat...') food_list = [] while True: food = yield food_list food_list.append(food) print(food_list) g = eater() # 得到生成器对象 g.__next__() # 初始化,让函数挂起在food = yield ,等待调用g.send()方法传值 g.send('food1') g.send('food2')
输出:
ready to eat... ['food1'] ['food1', 'food2']
3、三元表达式
res = 条件成立时候的返回值 if 条件 else 条件不成立的时候的返回值
x = 1 y = 2 res = x if x > y else y print(res)
4、列表生成式
[expression for item1 in iterable1 if condition1
for item2 in interable2 if condition2]
egg_list = [] for i in range(10): egg_list.append(f'egg{i}') print(egg_list)
相当于
print([f'egg{i}' for i in range(10)])
5、生成器表达式
创建生成器的第二种方法:
创建一个生成器对象,一种是调用yield关键字函数,另一种就是生成器表达式,与列表生成器的语法格式相同,只需要将[ ]换成( )也就是:
(expression for item in iterable if condition)
对比列表生成器返回的是一个列表,生成器表达式返回的是一个生成器对象
print([i ** 2 for i in range(10)]) print((i ** 2 for i in range(10)))
输出:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<generator object <genexpr> at 0x000001D03FBD2030>
对比列表生成式,生成器表达式的优点是节省了内存(一次值产生一个值在内存中)
6、生成式
6.1 列表生成式
print([i for i in range(10) if i > 2])
6.2 字典生成式
lst = ['张三', '李四', '王五'] dict1 = {i + 1: lst[i] for i in range(0, len(lst))}

浙公网安备 33010602011771号