浅谈迭代器协议、生成器、上下文管理协议

一、迭代器协议

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里面的异常

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值