Bộ đếm ngược cài `__iter__` và `__next__`
for trong Python không biết gì về danh sách hay chuỗi; nó chỉ gọi hai giao thức:
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-loop-basics.
Nội dung đề bài
Mô tả bài toán
for trong Python không biết gì về danh sách hay chuỗi; nó chỉ gọi hai giao thức: iter để lấy đối tượng duyệt và next để lấy từng phần tử, dừng lại khi gặp StopIteration. Bài này tự viết một bộ đếm ngược để thấy rõ hai lời gọi đó.
Yêu cầu
Cài đặt lớp Countdown:
- init(self, start): nhận số nguyên không âm; ném ValueError nếu start không
phải số nguyên hoặc là số âm. Giá trị này nằm trong self._start.
- iter(self): đưa bộ đếm về vị trí ban đầu self._start rồi trả về chính đối
tượng (self), để lớp có thể dùng lại nhiều lần trong nhiều vòng for.
- next(self): trả về số hiện tại rồi giảm đi 1; khi không còn số nào để trả thì
ném StopIteration. Mỗi lượt gọi trả một số int.
- drain(self): trả về danh sách tất cả số còn lại, bằng list(self).
- next_value(self): trả về số kế tiếp, tức next(self); có thể ném StopIteration.
- remaining(self): trả về số hiện tại đang chờ được trả.
Quy ước nộp bài
Nộp lớp Countdown trong solution.py. Hệ thống tự khởi tạo lớp bằng Countdown(start=...), gọi các phương thức trên đối tượng và bắt ngoại lệ ValueError / StopIteration; không dùng stdin/stdout.
Input
Hệ thống khởi tạo lớp bằng tham số từ khoá start, 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.
Output
Danh sách giá trị trả về theo đúng thứ tự gọi. drain trả về một danh sách số nguyên; nếu một lượt gọi ném StopIteration thì cả bộ test được coi là kịch bản ném lỗi.
Ràng buộc
- start là int không âm; 3.5 hay -1 đều không hợp lệ.
- iter phải đặt lại vị trí, nếu không lần duyệt thứ hai sẽ rỗng.
- next phải ném StopIteration khi start=0 hoặc khi đã đếm hết.
Ví dụ 1
Input
Countdown(init={"start": 3}, methods=[{"method": "drain"}])
Output
[[3, 2, 1]]
Ví dụ 2
Input
Countdown(init={"start": 0}, methods=[{"method": "drain"}, {"method": "remaining"}])
Output
[[], 0]
Giải thích
Countdown(start=3) thì drain() trả [3, 2, 1]. Khi start=2, gọi next_value(), remaining(), drain(), remaining() cho [2, 1, [2, 1], 0] vì drain đặt lại bộ đếm trước khi duyệt.
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.
