Trình quản lý ngữ cảnh
Thuộc phần Lập trình hướng đối tượng trong hành trình Python của Coddy. Bài học 41 trên 64.
Trình quản lý ngữ cảnh giúp bạn cấp phát và giải phóng tài nguyên đúng lúc cần thiết. Chúng đảm bảo việc dọn dẹp diễn ra đúng cách ngay cả khi có lỗi.
Đây là ví dụ phổ biến nhất khi dùng câu lệnh with:
with open('example.txt', 'w') as file:
file.write('Hello, world!')
# Tệp tự động đóng tại đâyTệp sẽ tự động đóng sau khối lệnh, ngay cả khi xảy ra ngoại lệ.
Tạo context manager của riêng bạn bằng cách triển khai các phương thức __enter__ và __exit__:
class MyContext:
def __enter__(self):
print("Entering the context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exiting the context")
return False # Đừng chặn các ngoại lệHãy dùng context manager tùy chỉnh của bạn:
with MyContext() as ctx:
print("Inside the context")Đầu ra:
Entering the context
Inside the context
Exiting the contextTạo một trình quản lý ngữ cảnh thiết thực hơn cho các kết nối cơ sở dữ liệu:
class DatabaseConnection:
def __init__(self, db_name):
self.db_name = db_name
self.connection = None
def __enter__(self):
print(f"Connecting to {self.db_name}")
self.connection = f"Connection to {self.db_name}"
return self.connection
def __exit__(self, exc_type, exc_val, exc_tb):
print(f"Closing connection to {self.db_name}")
self.connection = None
with DatabaseConnection("users_db") as conn:
print(f"Using {conn}")
print("Performing database operations...")Xử lý ngoại lệ trong trình quản lý ngữ cảnh:
class SafeContext:
def __enter__(self):
print("Setting up resources")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Cleaning up resources")
if exc_type:
print(f"An exception occurred: {exc_val}")
return False # Không chặn ngoại lệ
with SafeContext():
print("Working with resources")
# raise ValueError("Something went wrong") # Bỏ dấu chú thích để kiểm traĐầu ra:
Connecting to users_db
Using Connection to users_db
Performing database operations...
Closing connection to users_db
Setting up resources
Working with resources
Cleaning up resourcesPhương thức __exit__ nhận ba tham số:
exc_type: Kiểu ngoại lệ (hoặc None)exc_val: Giá trị ngoại lệ (hoặc None)exc_tb: Thông tin truy vết ngoại lệ (hoặc None)
Điểm chính: Trình quản lý ngữ cảnh dùng phương thức __enter__ và __exit__ để quản lý tài nguyên. Câu lệnh with tự động gọi các phương thức này, đảm bảo thiết lập và dọn dẹp đúng cách. Cách này đặc biệt hữu ích với tệp, kết nối cơ sở dữ liệu và các tài nguyên khác cần được dọn dẹp đầy đủ.
Thử thách
DễTrong thử thách này, bạn sẽ triển khai một lớp quản lý ngữ cảnh để đo thời gian đã trôi qua từ lúc vào đến lúc thoát khỏi một khối ngữ cảnh.
timer.py- Chứa phần triển khai lớpTimer(bạn sẽ chỉnh sửa tệp này)driver.py- Chứa các test case toàn diện (không chỉnh sửa)
Triển khai trình quản lý ngữ cảnh Timer trong timer.py theo các chú thích TODO. Lớp này cần:
- Ghi lại thời điểm bắt đầu khi vào ngữ cảnh
- Ghi lại thời điểm kết thúc khi thoát khỏi ngữ cảnh
- Tính toán và hiển thị thời gian đã trôi qua
Tự làm thử
from timer import Timer
import time
# Xử lý test case
test_case = input()
if test_case == "basic_test":
# Kiểm tra chức năng cơ bản
with Timer():
# Mô phỏng một tác vụ
time.sleep(2) # Lệnh này khiến chương trình chờ 2 giây
elif test_case == "nested_contexts":
# Kiểm tra các trình quản lý ngữ cảnh lồng nhau
with Timer():
time.sleep(1)
with Timer():
time.sleep(1)
elif test_case == "exception_handling":
# Kiểm tra cách xử lý ngoại lệ trong ngữ cảnh
try:
with Timer():
time.sleep(1)
raise ValueError("Test exception")
except ValueError as e:
print(f"Caught exception: {e}")
elif test_case == "zero_sleep":
# Kiểm tra với thời gian chờ tối thiểu
with Timer():
time.sleep(0.001)
elif test_case == "multiple_timers":
# Kiểm tra nhiều bộ đếm thời gian liên tiếp
with Timer():
time.sleep(1)
with Timer():
time.sleep(0.5)
with Timer():
time.sleep(2)
elif test_case == "as_decorator":
# Kiểm tra bộ đếm thời gian trong một hàm
def timed_function():
with Timer():
time.sleep(2)
timed_function()
else:
# Kiểm tra mặc định: chức năng cơ bản
with Timer():
# Mô phỏng một tác vụ
time.sleep(2) # Lệnh này khiến chương trình chờ 2 giây
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTham số selfPhương thứcThuộc tínhPhương thức khởi tạo (__init__)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnHàm super()Ghi đè phương thứcKế thừa đa lớpThứ tự phân giải phương thứcÔn tập: hệ thống phân cấp nhân viên2Decorator
Giới thiệu về decoratorDecorator thuộc tínhDecorator phương thức tĩnhDecorator phương thức lớp5Tính đa hình
Xem lại cách ghi đè phương thứcKiểu gõ vịtLớp và phương thức trừu tượngThiết kế giao diệnÔn tập: máy tính hình học8Các khái niệm OOP nâng cao
Kết hợp và kế thừaMixinPhương thức tĩnh và phương thức lớpDecorator lớpTrình quản lý ngữ cảnhTự luyện tập: Trình biên dịch Python online