Bộ ghi dấu khối lệnh với `__enter__` và `__exit__`
Câu lệnh with chỉ dựa vào hai phương thức: enter chạy khi mở khối và exit
Tiến độ của tôi ở bài này
Điểm và code bạn nộp được lưu vào tài khoản sau khi chấm bài.
Đang tải điểm của bạn…
Kiến thức và chủ đề
Kiến thức tiên quyết: python-basics, python-classes-intro, python-with-statement.
Nội dung đề bài
Mô tả bài toán
Câu lệnh with chỉ dựa vào hai phương thức: enter chạy khi mở khối và exit chạy khi rời khối, kể cả khi khối đó ném lỗi. Giá trị exit trả về quyết định có nuốt lỗi hay không. Tự viết một bộ ghi dấu khối lệnh là cách gọn nhất để thấy rõ cả hai lời gọi và thứ tự của chúng.
Yêu cầu
Cài đặt lớp Tracer:
- init(self, name="main"): nhận tên khối; ném ValueError nếu name không phải
chuỗi hoặc là chuỗi rỗng. Lưu tên trong self._name, danh sách sự kiện trong self._events, số khối đã mở self._opened và số khối đã đóng self._closed.
- enter(self): ghi thêm sự kiện chuỗi "enter:<tên>:<độ sâu>" với độ sâu là số
khối đang mở TRƯỚC khi mở khối này, rồi tăng self._opened; trả về self._name.
- exit(self, exc_type=None, exc=None, tb=None): tăng self._closed, ghi thêm sự
kiện "exit:<tên>:<độ sâu>" với độ sâu là số khối đang mở SAU khi đóng khối này, và trả về False để không bao giờ nuốt ngoại lệ.
- events(self): trả về bản sao danh sách sự kiện.
- depth(self): trả về số khối đang mở, tức self._opened - self._closed.
- measure(self): dùng chính cú pháp with self as name: rồi trả về name, để chứng
minh đối tượng dùng được như một trình quản lý ngữ cảnh.
Quy ước nộp bài
Nộp lớp Tracer trong solution.py. Hệ thống tự khởi tạo lớp bằng Tracer(name=...), gọi trực tiếp cả enter, exit lẫn các phương thức thường và bắt ngoại lệ ValueError; không dùng stdin/stdout.
Input
Hệ thống khởi tạo lớp bằng tham số từ khoá name, rồi gọi lần lượt các phương thức theo kịch bản của từng bộ test, kể cả gọi thẳng enter và exit.
Output
Danh sách giá trị trả về theo đúng thứ tự gọi. enter trả về tên khối, exit trả về False, events trả về danh sách chuỗi.
Ràng buộc
- Sự kiện có đúng dạng "enter:<tên>:<độ sâu>" hoặc "exit:<tên>:<độ sâu>".
- Độ sâu khi vào là số khối đang mở trước khi vào; khi ra là số khối đang mở sau khi ra.
- exit luôn trả False; việc mở và đóng khối không được nuốt ngoại lệ.
Ví dụ 1
Input
Tracer(init={"name": "main"}, methods=[{"method": "__enter__"}, {"method": "events"}, {"method": "__exit__"}, {"method": "events"}])
Output
["main", ["enter:main:0"], false, ["enter:main:0", "exit:main:0"]]
Ví dụ 2
Input
Tracer(init={"name": "load"}, methods=[{"method": "measure"}, {"method": "events"}])
Output
["load", ["enter:load:0", "exit:load:0"]]
Giải thích
Với name="main" rồi gọi enter(), events(), exit(), events() ta được "main", ["enter:main:0"], False, ["enter:main:0", "exit:main:0"].
Gợi ý và lời giải chỉ mở sau khi bạn bấm Nộp bài. Giáo viên và quản trị viên mở được ngay.
Góp ý & báo lỗi bài tập
Đề bài chưa rõ, test có vấn đề hay bạn có ý tưởng giúp bài tốt hơn? Gửi cho đội ngũ AI Empire nhé — mỗi góp ý đều được đọc.
