vivo版奥特曼系列ol最新版
1.19GB · 2025-11-28
try-finally 但更简洁)with 上下文表达式 as 变量名:
# 代码块(使用资源的逻辑)
# 代码块结束后,自动执行退出操作(无需手动关闭)
open()、自定义的 对象 实例)__enter__() 方法返回的值(不是管理器对象本身一个对象能被with使用,必须实现两个特殊方法
__enter__(self):进入 with 代码块时执行。
as 后的变量名__exit__(self, exc_type, exc_val, exc_tb):退出 with 代码块时执行(无论正常结束还是异常结束)
True 表示忽略异常。示例:自定义简单上下文管理器
class MyFileReader:
def __init__(self, file_path):
self.file_path = file_path
self.file = None # 进入with代码块时执行
def __enter__(self):
self.file = open(self.file_path, 'r', encoding='utf-8')
return self.file # 返回文件对象,赋值给as后的变量 # 退出with代码块时执行
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close() # 自动关闭文件
# 若返回True,会忽略代码块中的异常;返回None/False则会抛出异常
return False
# 使用 with
MyFileReader('test.txt') as f:
content = f.read() # 直接使用__enter__返回的文件对象
# 代码块结束后,自动调用__exit__关闭文件
替代手动open()/close(),避免忘记关闭文件
# 正确用法:自动关闭文件
with open('test.txt', 'r', encoding='utf-8') as f:
content = f.read()
# 等价于(但更简洁)
f = open('test.txt', 'r', encoding='utf-8')
try:
content = f.read()
finally:
f.close()
只有实现了 __enter__ 和 __exit__,才能直接用 with
可在一个 with 中管理多个资源(用逗号分隔),按顺序进入、逆序退出:
# 同时打开两个文件,自动关闭
with open('a.txt', 'r') as f1, open('b.txt', 'w') as f2:
content = f1.read()
f2.write(content)
自动释放连接,避免连接池耗尽:
import pymysql
with pymysql.connect(host='localhost', user='root', password='123456', db='test') as conn:
with conn.cursor() as cursor:
cursor.execute('SELECT * FROM users')
result = cursor.fetchall()
# 自动关闭cursor和conn
as 后的变量是 __enter__ 的返回值,不是上下文管理器对象:
open() 的 __enter__ 返回文件对象,所以 as f 中 f 是文件对象,不是 open() 的返回值MyFileReader 中 __enter__ 返回 self,所以 reader 是 MyFileReader 实例,可调用其方法。__exit__ 仍会执行(保证资源释放)__exit__ 返回 True,异常会被静默处理(不抛出);返回 False 或 None,异常会正常抛出with
__enter__ 和 __exit__ 方法(即「上下文管理器协议」)open()、threading.Lock、pymysql.connect、自定义实现协议的类with 能简化代码并避免遗漏contextlib简化自定义上下文管理器如果不想手动实现 __enter__ 和 __exit__,可使用 contextlib.contextmanager 装饰器(基于生成器):
from contextlib import contextmanager
@contextmanager
def my_file_reader(file_path):
# 相当于__enter__的逻辑
f = open(file_path, 'r', encoding='utf-8')
yield f # 返回值赋值给as后的变量,暂停在这里执行代码块
# 代码块结束后,执行以下(相当于__exit__的逻辑)
f.close()
# 使用方式不变
with my_file_reader('test.txt') as f:
content = f.read()