一、迭代器协议
1.迭代器协议是指:对象必须提供一个__next__()方法
2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义了一个__iter__方法)
像(字符串、列表、元组、字典、集合、文件对象等)并不是迭代器对象,只是因为他们有__iter__()方法,把他们
转成了可迭代对象,才能有一个next()方法
#-------------------
#for循环的工作机制就是基于迭代器的工作机制
# for i in s:#故for循环其实做的就是上面的那几步
# print(i)
#-----------------
#用while循环模拟for循环做的事情
# l = [1,2,3,4,5]
# diedai_l = l.__iter__()
# while True:
# try:
# print(diedai_l.__next__())
# except StopIteration:
# print('迭代完毕,循环终止了')
# break
l = ['die','erzi','sunzi','chongsunzi']
iter_l = l.__iter__()
# print(iter_l.__next__())
# print(iter_l.__next__())
# print(iter_l.__next__())
# print(iter_l.__next__())
# print(iter_l.__next__())
#-----------------------
#next()和上面的__next()__效果是一样的,只不过next()是系统提供的,不像__next()__是为迭代器对象提供的
# print(next(iter_l))
# print(next(iter_l))
# print(next(iter_l))
# print(next(iter_l))
二、生成器初探
1.什么是生成器?
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要自己内置的__iter__方法),所以生成器就是可迭代对象
2.生成器分类及在python中的表现形式:(Python有两种不同的方式提供生成器)
a.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次在它离开的地方继续执行
b.生成式表达式:类似于列表推导,但是,生成器返回按量产生结果的一个对象,而不是一次构建一个列表,节省内存
'''
# def test():
# # yield 1
# # yield 2
# # yield 3
# # g = test()
# # print(g)#<generator object test at 0x02B83EA0>
# # print(g.__next__())#1
# # print(g.__next__())#2
# # print(g.__next__())#3
#从上面就可以看出,g就是一个生成器对象,yiled就相当于
# return,只是yiled可以返回多次
#egg_list = ['鸡蛋%s'%i for i in range(100000000)]产生的是真实占内存的列表,
# 会很占内存,故我们来用生成器表达式来解决这个问题
# egg_list = ('鸡蛋%s'%i for i in range(10))#生成器表达式,就是一个迭代器对象
# print(egg_list)#<generator object <genexpr> at 0x031A3EA0>
# print(egg_list.__next__())
# print(egg_list.__next__())
# print(egg_list.__next__())
# print(egg_list.__next__())
#生成式表达式比较节省内存,你需要多少量,他就给你生成多大的量,
#不像列表,把所有量全部存到内存,要多少取多少
三、上下文管理协议
# f = open('a.txt','w')#open函数返回了一个对象
class Open:
def __init__(self,name):
self.name = name # name: a.txt
print("name:",self.name)
def __enter__(self):
print('执行enter')
print("self:",self) # self: <__main__.Open object at 0x0000018E6E2E24C8>
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('执行exit')
# return True #会吞掉with里面的异常
with Open('a.txt') as f:
print(f)
print('===>')
print('===>')
# print(sda)
print('===>')
print('===>')
#实例化Open触发__enter__,with里面的语句执行完的时候触发__exit__
#当with里面抛异常的时候会直接执行__exit__
#==============好处===========
'''
1.在需要管理一些资源比如文件,网络链接和锁的编程环境中,可以
在__exit__中定制自动释放资源的机制,你无须再去关心这个问题
'''
从上述代码的注释打印结果,我们分析
实例化Open类的时候,先执行__init__方法,把参数传给name,所以name=‘a.txt’,然后触发__enter__方法,返回给我们这个类对象,最后当我们执行完with里面的语句后,触发__exit__方法。
当with语句中有错误,会触发__exit__方法,程序抛出异常,阻断执行。想要让程序跳过这个异常,需要重写__exit__方法,设置返回值return True,会吞掉with里面的异常