一:迭代器
1.迭代器协议:是指迭代器对象必须提供一个next()方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常来中止迭代(如下一项不存在的时候),只能向后走而不能向前退。
2.可迭代对象:满足迭代器协议的对象(python中通过对象内部定义一个__iter__()方法来实现迭代器对象)
列表,字符串,元组等并不是迭代器对象,只是在使用for循环,max等工具时调用了他们内部的__iter__()方法返回了一个可迭代对象来进行迭代的操作(for循环会自动捕捉StopIteration异常来中止迭代)。
x=[1,2,3,4,5,6] iter_test=x.__iter__() print(iter_test) print(iter_test.__next__()) print(iter_test.__next__()) print(iter_test.__next__()) print(iter_test.__next__()) print(iter_test.__next__()) print(iter_test.__next__())
#利用python自带的next()内置方法也可以,效果等同于__next__()
print(next(iter_test))
结果:<list_iterator object at 0x000001EAF26E8E48>
1
2
3
4
5
6
二: 生成器
1.生成器自动实现了可迭代协议,可以理解为生成器就是可迭代对象。
2.生成器函数是在函数中使用yield时返回的时生成器对象。
def test(): print("aa") print("bb") yield [1,2]#当运行至此时,函数挂起,当再次运行next方法时,函数会从当前位置继续运行。 print("dsa") yield 2 print("fsd") yield 3 res=test() print(res.__next__()) print(res.__next__()) print(res.__next__()) # 输出:aa # bb # [1, 2] # dsa # 2 # fsd # 3 #三元运算 a=2 res=1 if a==2 else 3 print(res) #列表解析 l=[i for i in range(10)] #三元运算和列表解析结合 l=[i for i in range(10) if i>5] #l=[i for i in range(10) if i>5 else 3]此时不可以,没有四元表达式 #把列表解析的[]换成(),就会得到生成器表达式 l=(i for i in range(10)) l.__next__() sum(i for i in range(10))#利用生成器表达式可减少内存占用
3.发蛋案例感受生成器函数好处:
# #缺点1:占空间大 # #缺点2:效率低 # def xiadan(): # ret=[] # for i in range(100): # ret.append(i) # return ret # print(xiadan()) #生成器函数,来一个给一个 def xiadan(): for i in range(100): yield i res=xiadan() print(res.__next__()) print(res.__next__())
4.其他例子(注意,生成器只能被迭代一次):
#占用内存大 sum([i for i in range(10000)]) #占很少内存 sum(i for i in range(10000)) #假设文件内容为: {'name':'weq','population':20} {'name':'ewqe','population':5} {'name':'fsd','population':6} def get_pop(): with open('b.txt','r') as f: for i in f: yield i g=get_pop() s1=eval(g.__next__())#将字符串转换为字典 print(s1['population']) #统计总人口 sum(eval(i)['population'] for i in g)