Python函数之生成器
1.生成器
1.1生成器介绍
python函数中的三大器:
- 迭代器
- 生成器
- 装饰器
生成器本质就是迭代器,内部含有__iter__
以及__next__
方法,也是通过next方法进行取值,与迭代器几乎一模一样。迭代器都是python的内置函数(方法)给你返回的,或者是我们通过对可迭代对象进行转化得到的,生成器我们可以通过代码构建。
创建生成器的两种方式;
- 生成器函数创建生成器。
- 生成器表达式。
1.2 生成器函数
通过关键字yield构建生成器函数。
def func():
print(111)
print(222)
yield 'barry'
# 函数中出现yield他就是生成器函数。
obj = func()
print(obj) # <generator object func at 0x102ebce08> 生成器对象
我们如何对一个迭代器或者对一个生成器取值?也是通过next方法。
def func():
print(111)
print(222)
yield 'barry'
obj = func()
# print(obj) # <generator object func at 0x102ebce08> 生成器对象
print('----->', next(obj))
next一次对应一个yeild,yield相当于一个节点,next一次,对生成器获取一次值,生成器函数就会产生一个值(yield后面的值),停止。
def func():
print(111)
print(222)
yield 'barry'
yield 1
yield 2
yield 666
print(333)
print(555)
yield [22, 33]
# 函数中出现yield他就是生成器函数。
obj = func()
# print(obj) # <generator object func at 0x102ebce08> 生成器对象
print('----->', next(obj))
print(next(obj))
print(next(obj))
print(next(obj))
print(next(obj))
print(next(obj))
- yield 与 return的区别
- return终止函数,return给函数的执行者返回值。
- yield不会终止生成器函数,yield是给next返回值。
1.3 验证生成器(迭代器)的特性
生成器(迭代器)一直向下取值,不回头,每次取值都会记录当前的位置。
# 楼下卖煎饼,用两种思想去做,可迭代对象的思想,迭代器的思想去做。
# 可迭代对象
# lst = [f'{i}号煎饼' for i in range(1, 501)]
# print(lst)
# for i in lst:
# print(i)
# if i == '10号煎饼':
# break
#
# for i in lst:
# print(i)
# if i == '30号煎饼':
# break
# 生成器函数
def func():
for i in range(1, 501):
yield f'{i}号煎饼'
obj = func() # 返回一个生成器对象
for i in range(10):
print(next(obj))
for j in range(20):
print(next(obj))
对比代码得知:
- 可迭代对象一次性将全部的值都加载内存,每次新的for循环都会从开始取值,不会记录位置。
- 迭代器,next一次,生产一个值,再next一次,(上一个生产的值在内存中消失)再生产一个值,每次都会记录位置。
- 举例:买多个篮子鸡蛋放在家中(可迭代duixaing)与买一个可以无限下蛋的老母鸡(迭代器)的区别。
1.4 yield from
python3x增加的一个功能。
def func():
lst = [1, 2, 3]
for i in lst:
yield i
obj = func()
print(next(obj))
print(next(obj))
print(next(obj))
def func():
lst = [1, 2, 3]
yield from lst
obj = func()
print(next(obj))
print(next(obj))
print(next(obj))
yield from 优点:代替函数内部的for循环,提升效率。
1.5 生成器表达式
与列表推导式几乎一模一样,就是将[]换成()。
-
两种模式
-
循环模式
[变量(格式化的变量) for 变量 in iterable]
-
筛选模式
[变量(格式化的变量) for 变量 in iterable if 条件]
-
-
测试
obj = (i for i in range(1, 11)) # print(obj) # print(next(obj)) # print(next(obj)) obj = (f'python{i}期' for i in range(1, 11) if i != 7) # print(obj) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj))
1.6 对生成器(迭代器)取值的三种方式
-
next方法
-
可以通过for循环
-
数据类型的转化(一般是转化成列表)。
obj = (f'python{i}期' for i in range(1, 11) if i != 7) # print(obj) # print(next(obj)) # print(next(obj)) # print(next(obj)) # print(next(obj)) # print(next(obj)) # print(next(obj)) # print(next(obj)) for i in obj: print(i) def func(): for i in range(1, 51): yield f'{i}号煎饼' obj = func() # 返回一个生成器对象 print(list(obj)) obj = (f'python{i}期' for i in range(1, 11) if i != 7) print(list(obj))