with
语句介绍:
python的with
语句是一种用于简化资源管理的语法结构。
它主要用于确保在代码块执行完毕后,正确地释放资源,例如文件操作、锁、网络连接等。
with
语句可以确保即使在发生异常的情况下,资源也能被正确地关闭和清理。
只要一个类实现了以下两个方法就可以使用with
语句。
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
pass
一般是上下文协议的对象或者资源管理器中使用with
。
实现了__enter__
和__exit__
都是上下文或者资源管理器。
常见的使用
with open('a.txt', 'r') as f:
content = f.read()
print(content)
使用open
函数以只读模式 打开文件a.txt
。with
语句确保文件在操作完成后会被正确关闭,即使发生异常也是如此。文件的内容被读取到content
变量中。打印出文件的内容。
显然这是没有营养的~
不知道我们没有思考过这么一个问题?上述代码中的f
变量是一个什么是东西?
我在刚接触python的这个语法的时候,会认为f
就是open()
对象的返回值。后来发现是我肤浅了。
看下这段代码,自定义一个资源管理器类实现__enter__
和__exit__
。
class MyResourceManager:
def __enter__(self):
print("Resource is being init...")
a = 1
print(a) # 1
def __exit__(self, exc_type, exc_value, traceback):
b = 2
print(b) # 2
print("Resource is being cleaned up.")
with MyResourceManager() as resource:
print("Using the resource")
print(type(resource)) # <class 'NoneType'>
print(resource) # None
print("Test End")
你会发现这里的resource
是一个None
, 按道理应该是MyResourceManager
类型的。
直接说一下结果,with MyResourceManager() as resource
这里的resource
是MyResourceManager
里__enter__
函数的返回值。大部分使用with
好像都是前面对象本身的类型,那是因为__enter__
函数返回了self
对象本身。
with XX as resource
不是上下文或资源管理器对象,是enter
方法的返回值 。
在看份代码,也许还会有发现~
class MyResourceManager:
test_lst = ["a", "b", 12]
def __enter__(self):
print("Resource is being init...")
print(self.test_lst) # ['a', 'b', 12]
return self
def __exit__(self, exc_type, exc_value, traceback):
self.test_lst[2] = "c"
print("Resource is being cleaned up")
with MyResourceManager() as resource:
print("Using the resource")
print(type(resource)) # <class '__main__.MyResourceManager'>
print(resource.test_lst) # ['a', 'b', 12]
lst = resource.test_lst # 取资源管理器里面的值
print(lst) # ['a', 'b', 12]
print(lst) # ['a', 'b', 'c']
print("Test End")
看到这里我想with
语句就应该差不多了,为什么倒数第二行打印是['a', 'b', 'c']
。
with语句在进入时候会执行__enter__
在离开的时候会执行__exit__
。
显然在上述代码中with
结束的时候,对test_lst
进行了修改,test_lst
变量是一个对象,所以with
结束的时候,外部lst
的值会发生改变。
最后一个问题,如果上述代码test_lst
改成int
或str
,with
离开时修改test_lst
,最后with
外打印的lst
值会变吗?
在线等你的答案~