作用:生成器主要用于提高代码效率、节约内存空间,在python中,没有被调用的对象会被销毁。
# 之前学过列表生成式
s = [i for i in range(10)]
print(s) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 创建一个生成器
s = (i for i in range(10))
print(s) # at 0x000001BF5E2107B0>
与列表相比,列表创建的10个数值都在内存中开辟了空间,而生成器只有当前调用才创建的一个内存空间。打个比方,列表相当于10道菜,而生成器则是能做这10道菜的一个厨师,当被调用时,就会制作其中一个菜品。
#创建生成器的两种办法
# 1. 生成器表达式
g = (i for i in range(1,6))
print(s) # at 0x000002010C5D07B0>
# 2. 使用 yield 关键字
def func():
print('f1')
print('f11')
yield 1
print('f2')
yield 2
print(func()) #
#注意:func()才是生成器对象,而不是func
在版本python2中使用语法:
生成器对象.__next__()
在版本python3中还可以使用语法:
next(生成器对象)
# 生成器的调用语法
s = (i for i in range(3))
# print(s.__next__()) # 版本python2 调用生成器的语法
print(next(s)) # 0
print(next(s)) # 1
print(next(s)) # 2
# print(next(s)) # 报错
每一次调用生成器,会返回单个值,直到生成器中没有值了,程序就会报错。
# yield创建的生成器调用
def f():
print('f1',end=' ')
print('f11')
yield 1
print('f2')
yield 2
j = 0
for i in f():
print(i,'-->',j)
j +=1
============
f1 f11 # 第一次调用输出了f1和f11
1 --> 0 # 第一次调用结束还输出了1
f2 # 第二次调用输出f2
2 --> 1
yield 关键字,函数调用时一旦执行到该行,就会停止执行并且返回yield的值,并且存档,下一次调用函数的时候,从该存档处继续执行。
yield 和return有一定区分:
return:在函数中返回某个值,然后函数结束运行,一般没有返回值类型,就不用写return
yield:带yield的函数是一个生成器,在函数内部碰到这个yield的时候,函数会返回某个值,当下次执行函数后,会在上次停留的位置继续运行。
从现象上看,能使用for循环的都是可迭代对象;
从本质上看,存在内置函数__iter__方法的是可迭代对象。
# 可迭代对象的特点
# 1.能用for循环
# 2.内置函数存在 __iter__()
l = [2, 4, 6]
for i in l:
pass
l.__iter__()
t = (1, 2, 3)
for i in t:
pass
t.__iter__()
d = {'name': 'huoying'}
for i in d:
pass
d.__iter__()
注意:
作用:提供一种有效的方式来遍历数据集合。
如何分辨迭代器?迭代器的两个必存在的特点:
l = [1,2,3]
# l.__next()__ # 列表没有next()方法
d = iter(l) # iter()方法将返回迭代器d
print(d)
print(next(d))
arr = iter([1,2,3])
for i in arr:
print(i)
相较于while循环,while循环不能自动处理异常
# while不处理异常的话,程序会报错,因为第4次循环,迭代对象已经没有内容了
arr = iter([1,2,3])
while True:
print(next(arr))
# 加入处理异常try功能
arr = iter([1, 2, 3])
while True:
try:
print(next(arr))
except StopIteration:
break