函数三大器之生成器
生成器(generator)
1.什么是生成器?
生成的工具。生成器是一个 "自定义" 的迭代器, 本质上是一个迭代器。
2.如何实现生成器
但凡在函数内部定义了的yield,调用函数时,函数体代码不会执行,会返回一个结果,该结果就是一个生成器。
yield: 每一次yield都会往生成器对象中添加一个值。
注意:
-
yield只能在函数内部定义
-
yield可以保存函数的暂停状态
def func(): # 定义一个函数
print('from func')
yield 'tank' # 定义yield,需要添加什么值就在后面直接添加
res = func()
print(res) # 打印的结果就是一个生成器,并且直接打印是不会执行函数体代码的
def func():
print('from func')
yield {'tank':'sean'} # yield后面可以添加多个类型的值,如果是多个字符串,返回的是元组,如果以字典的形式添加返回的是字典
res = func()
print(res.__next__()) # 只有以res.__next__()或者next(res)的形式才会执行函数体代码并将添加的值取出来
def func():
print('开始准备下蛋')
print('1---火鸡蛋1')
yield '火鸡蛋1' # 每一次yield就往生成器里面添加一次值
print('2---火鸡蛋2')
yield '火鸡蛋2'
print('3---火鸡蛋3')
yield '火鸡蛋3'
print('取最后一个蛋,查看是否有')
res = func()
print(next(func())) # 只会取第一次添加的值
print(next(func()))
print(next(func()))
# 上下两种情况是不一样的
# print(next(res)) # 会一个一个将添加的值取出来
# print(next(res))
# print(next(res))
def func(): # 循环yield添加值
n = 0
print('开始准备下蛋')
while n < 4:
print(f'1---火鸡蛋{n}')
yield f'火鸡蛋{n}'
n += 1
res = func()
while True: # 循环取值
try: # 注意,只有取出来上面的函数体才会正常运行
print(next(res))
except StopIteration:
break
yield与return比较:
相同点:返回值的个数都是无限制的。
不同点: return只能返回一次值,yield可以多次使用返回多个值
3.for循环里面的range
注意:在python2中,for 循环里面的range(1,5)----->得到的是列表[1, 2, 3, 4]
在python3中,for循环里面range(1,5)---->得到的是一个生成器,本质上就是一个迭代器
# 自定义range功能,创建一个自定义的生成器
# (1, 3) # start--> 1 , end---> 5, move=2
def my_range(start, end, move=1): #
while start < end:
yield start
start += move
g_range = my_range(1, 5)
print(g_range) # 本质是一个生成器
print(next(g_range))
输出结果:
<generator object my_range at 0x00000289B10A8348>
1
for line in g_range:
print(line)
输出结果:
1
2
3
4
for line in my_range(1, 5, 2):
print(line)
输出结果:
1
3
列表生成式
1.什么是列表生成式?
可以一行代码实现列表
语法:
list = [取出的每一个值、任意值 for 可迭代对象中取出的每一个值 in 可迭代对象]
注意:
for的右边是循环次数,并且可以取出可迭代对象中每一个值
for的左边可以为当前列表添加值
list = [值 for 可迭代对象中取出的每一个值 in 可迭代对象]
list = [值 for 可迭代对象中取出的每一个值 in 可迭代对象 if 判断]
一般情况:
l1 = [] # 先定义一个空集合
l2 = [1, 2, 3, 4,]
def func():
for i in l2:
l1.append(i) # 逐个添加元素
print(l1)
func()
列表生成式
l1 = [1, 2, 3, 4, 5]
l2 = [i for i in l1]
或
l2 = [i for i in range(1,6)]
print(l2)
将name_list列表中的jason过滤掉,其他人后缀都添加_dsb
name_list = ['jason', '饼哥(大脸)', 'sean', 'egon', 'tank']
new_name_list = [name + '_dsb' for name in name_list if not name == 'jason'] # 可以添加if进行判断
print(new_name_list)
2.生成器表达式和列表生成器对比
生成器表达式(生成器生成式):
- 列表生成式: 若数据量小时采用
[line for line in range(1, 6)] ---> [1, 2, 3, 4, 5]
优点: 可以依赖于索引取值,取值方便
缺点: 浪费资源
- 生成器生成式: 若数据量过大时采用
() ---> 返回生成器
(line for line in range(1, 6)) ---> g生成器(1, 2, 3, 4, 5)
优点: 节省资源
缺点: 取值不方便
# 生成一个有1000个值的生成器
g = (line for line in range(1, 1000001))
# <generator object <genexpr> at 0x00000203262318E0>print(g)
# 列表生成式实现
list1 = [line for line in range(1, 1000001)]
print(list1)
三元表达式
1.什么是三元表达式?
三元表达式就是将if...else...分支变成一行代码
语法:
条件成立返回左边的值 if 判断条件 else 条件不成立返回右边的值
举例:
def func(a, b):
if a > b :
return a
else:
return b
print(func(3,5))
# 写成三元表达式形式
def func(a,b):
res = a if a > b else b
print(res)
func(5,3)