高级编程技巧 学习笔记
一、Python 中的 with 语句
1.1、什么是上下文
-
python 中的上下文,指的就是代码所执行的环境状态,或者运行的场景。
-
python 上下文管理器规定了某个对象的使用范围,当进入或者离开了使用范围,会有相应的操作,多用于资源的分配和释放上,即在开始时分配资源,结束时释放资源。
-
如文件的读写,在读写前,需要先打开文件,在读写完成后,需要关闭文件。再如数据库的操作,在操作前,需要先连接数据库,结束后,需要释放连接等。
1.2、使用 try … except … 实现上下文(以读写文件为例)
try:
f = open('test.txt', 'w')
# print("code")
raise KeyError
except KeyError as e:
print('Key Error')
f.close()
except IndexError as e:
print('IndexError')
f.close()
except Exception as e:
print(e)
f.close()
finally:
# 不管有没有异常都会运行
print('end')
f.close()
代码冗余,且容易漏写(忘记关闭,没有释放资源)。
1.3、定义类实现上下文
-
必须有
__enter__(self)
方法获取资源 -
必须有
__exit__(self, exc_type, exc_val, exc_tb)
方法释放资源 -
有错误时才能看到
__exit__
方法的几个参数
class Sample():
# 实例化后调用方法前
def __enter__(self):
print("start")
return self
def demo(self):
print("this is demo")
def demo2(self):
print("this is demo2")
# 释放资源的时候(结束程序时)
def __exit__(self, exc_type, exc_val, exc_tb):
print("exc_type: ",exc_type) # 异常类 <class 'AttributeError'>
print("exc_val: ",exc_val) # 异常值 'Sample' object has no attribute 'dems'
print("exc_tb: ",exc_tb) # 跟踪信息 <traceback object at 0x000001AC339178C8>
print("end")
with Sample() as sample:
sample.demo()
sample.demo2()
# sample.dems()
比较麻烦,一定要定义 __enter__
和 __exit__
方法。
1.4、使用 contextlib 与 yield 实现上下文
import contextlib
@contextlib.contextmanager
def file_open(filename):
print("file open")
# yield {} # yield 的返回值类型无所谓
yield [] # 不能用 return, return 会结束 yield 不会结束
print("file close")
with file_open("demo.txt") as f:
print("66666")
print("88888")