一、核心要义
1. for, while和try语句的else字句
2. with语句和上下文管理器
二、代码示例
1、else块
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/2/28 20:14
# @Author : Maple
# @File : 01-else块.py
# @Software: PyCharm"""
用在for循环,while语句 和try...except中的else块
"""
from random import randintdef gen():return randint(1,6)if __name__ == '__main__':# 1.for循环中 else的使用:只有当for循环正常遍历完,才会执行elseprint('****1.for循环中 else的使用***********')my_list = ['Maple','Kelly']for i in my_list:if 'Max' == i :breakelse:print('Max is not in mylist')# 2.while语句中else块使用:没有被break语句中止,顺利循环执行完毕,才会执行else模块中的语句print('****2.while语句中else的使用***********')i = 0while i < 3:i +=1if gen() == 1:breakelse:print('while顺利执行完毕')# 3 try..except中使用else:没有错误被捕获时,才会执行elseprint('****3.try..except语句中else的使用***********')try:print(1)except Exception as e:print(e)else:print('没有错误,顺利执行完毕')
2、上下文管理器和with块
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/2/28 20:33
# @Author : Maple
# @File : 02-上下文管理器和with块.py
# @Software: PyCharmdef fun():with open('data/scores') as fp:"""1. with open() 返回的是一个上下文管理器(包含__enter__和__exit__方法),此例中的上下文管理器是TextIOWrapper类的实例,with语句在开始运行的时候就会进入管理器的__enter__方法2. __enter__方法返回的对象,通过as 语句赋值给fp,此例__enter__方法返回的刚好的是管理器本身(self).其实__enter__方法也可以返回其它值,甚至是None(此时with语句也无需通过as接收值)"""lines = fp.readlines()for line in lines:print(line)class LookingGlass:def __enter__(self):import sysself.original_write = sys.stdout.write# 将标准输出反向sys.stdout.write = self.reverse_writereturn 'JABBERWOCKY'def reverse_write(self,text):self.original_write(text[::-1])def __exit__(self, exc_type, exc_val, exc_tb):import syssys.stdout.write = self.original_writeif exc_type is ZeroDivisionError:print(r"Please don't divide by zero!")# 告诉解释器,异常已经处理return True# 如果exit方法返回None,或者True之外的值,with块中的任何异常都会向上冒泡if __name__ == '__main__':# 1. fun函数测试"""100 200 300400 500 600"""fun()# 2.使用 LookingGlass# LookingGlass类enter方法的返回值 JABBERWOCKY 会赋值给whatwith LookingGlass() as what:# 由于标准输出已经反向,所以下面的字符也会反向输出print('Alice,Kitty and Snowdrop') # pordwonS dna yttiK,ecilA# JABBERWOCKY反向输出print(what) # YKCOWREBBAJ# with语句结束, sys.stdout.write恢复成正常,所以what会正常输出print(what) # JABBERWOCKY# 3.with语句之外使用 LookingGlassprint('****3.with语句之外使用 LookingGlass***********')manager = LookingGlass()## 执行完之后 标注输出就反向了monster = manager.__enter__()print(monster) # YKCOWREBBAJ## 执行完exit方法,标准输出恢复正常manager.__exit__(None,None,None)print(monster) # JABBERWOCKY
3、contextmanager
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/2/28 22:12
# @Author : Maple
# @File : 03-contextmanager.py
# @Software: PyCharm"""
该装饰器将简单的生成器函数变成 上下文管理器,这样就不用创建类去 实现管理器协议
"""
from contextlib import contextmanager"""contextmanager的功能:把生成器包装成实现了__enter__和__exit__方法的类
1.__enter__方法的作用:
(1)调用生成器函数,保存生成器对象(这里将其称为gen)
(2)调用next(gen),执行到yield关键字所在的位置
(3)返回next(gen)产出的值,绑定到with/as 语句中的目标变量上
2.__exit__方法的作用:
(1)检查有没有把异常传给exc_type,如果有,调用gen.throw(exception),在生成器函数定义体中包含yield关键字的那一行抛出异常**注意:如果生成器函数中,没有处理异常的代码,生成器函数就会终止(在yield行),不会执行下面的代码,因此可能导致有些收尾工作无法完成
(2)否则,调用next(gen),继续执行生成器函数定义体中yield语句之后的代码Tips:在@contextmanager装饰器装饰的生成器中,yield与迭代没有任何关系,更像是协程:执行到某一点暂停,让客户代码运行,直到客户让协程继续运行
"""@contextmanager
def LookingGlass():import sysoriginal_write = sys.stdout.writemsg = ''def reverse_write(text):original_write(text[::-1])# 将标准输出反向sys.stdout.write = reverse_write# yield之前的部分,相当于是上下文管理器的__enter__函数内容# 为了避免因为抛出异常,yield之后的代码无法执行,这里写成try..except..finally的形式try:yield 'JABBERWOCKY'# yield之后的部分,相当于是上下文管理器的__exit__函数内容except ZeroDivisionError:msg = 'please do not divide by zero!'finally:sys.stdout.write = original_writeif msg:print(msg)if __name__ == '__main__':with LookingGlass() as what:# 由于标准输出已经反向,所以下面的字符也会反向输出print('Alice,Kitty and Snowdrop') # pordwonS dna yttiK,ecilA# JABBERWOCKY反向输出print(what) # YKCOWREBBAJprint(what) # JABBERWOCKY