上下文管理器即 with
语句,这是 python 独有的语句。
with
常用于文件操作,with
语句执行结束后被打开的文件自动关闭,代码更简洁:
with open("myfile.txt", 'r') as file:
pass
其中,open
是一个class。
也可以实现自定义的 上下文管理器,例如,如下数据库操作代码有很多重复,不管是创建,更新还是删除,每次都要连接数据库,关闭数据库,为了避免这种重复,可以将这些每次都要执行的代码写到一个上下文管理器,即一个类中。
def get_all_books():
connection = sqlite3.connect('data.db')
cursor = connection.cursor()
cursor.execute("SELECT * FROM books")
books = [{'name': row[0], 'author': row[1], 'read': row[2]} for row in cursor.fetchall()]
connection.close()
return books
def add_book(name, author):
connection = sqlite3.connect('data.db')
cursor = connection.cursor()
cursor.execute(f'INSERT INTO books VALUES(?, ?, 0)', (name, author))
connection.commit()
connection.close()
上下文管理器的实现:
import sqlite3
class DatabaseConnection:
def __init__(self, host):
self.connection = None
self.host = host
def __enter__(self):
self.connection = sqlite3.connect(self.host)
return self.connection
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type or exc_val or exc_tb: # in case of any error, close the connection without commit
self.connection.close()
else:
self.connection.commit()
self.connection.close()
数据库的代码因此可以简化:
def add_book(name, author):
with DatabaseConnection('data.db') as connection:
cursor = connection.cursor()
cursor.execute(f'INSERT INTO books VALUES(?, ?, 0)', (name, author))
def get_all_books():
with DatabaseConnection('data.db') as connection:
cursor = connection.cursor()
cursor.execute("SELECT * FROM books")
books = [{'name': row[0], 'author': row[1], 'read': row[2]} for row in cursor.fetchall()]
return books