← 返回 xai 的题目列表Resumable Iterator with Save / Restore State
类型:qbank
Design and implement an iterator that can persist its position to a checkpoint and resume from that checkpoint later, including across process restarts. The bar is a clean state model + correct boundary semantics on the resume path; the follow-up extends to nested iterators (iterator-of-iterators).
Requirements
Implement an iterator class with at least:
__next__() returning the next element and advancing.
save_state() → bytes | dict — a serializable snapshot sufficient to resume.
restore_state(state) (or factory from_state(...)) — rebuild an iterator that continues exactly where the saved one left off, including deterministic order.
Support arbitrary underlying iterables (list, generator, file lines).
Follow-up:
Compose a resumable iterator over a stream of resumable iterators (e.g. chain(iter1, iter2, …)), where the saved state must record both the outer index and the inner iterator's state.
Notes
Test cases in this round were Python; Java / non-Python candidates had to write their own scaffolding.
A common bug: the snapshot is taken after __next__() returns, but resume re-yields the last element. Decide and document whether save_state() records "position before next call" or "position after last yield," and stay consistent.
For the nested follow-up: store (outer_index, inner_state). Restoring requires reconstructing the outer iterable up to outer_index and then restore_state(inner_state) on the inner. If outer iterables are also generators, you need them to be reproducible (seed / re-open file) rather than one-shot.
The interviewer's expected complexity: save_state() and restore_state() should be O(1) for list-backed iterators, O(k) for generators that must replay.
Test-case authoring took meaningful time for non-Python candidates in this round — plan to spend the first 5 minutes on scaffolding if you bring Java or Go.
Preparation
Implement ResumableListIterator(items, index=0) with explicit save_state / from_state in under 10 minutes.
Practice the nested case on paper before coding: which fields go in the saved blob, and how restore reconstructs them.
Be ready to discuss the file / generator case — what happens when the underlying source is not deterministic, and how to fall back to materializing into a list.
Python already gives you a canonical hook for this: __getstate__() / __setstate__(state) on the iterator class — save_state returns whatever __getstate__ would (typically self.__dict__.copy() with unpicklable handles stripped), and restore_state does what __setstate__ does (rehydrate fields, re-open file at seek(offset), reseed RNG). Reusing the protocol means pickle.dumps(it) / pickle.loads(blob) works for free, which is the cleanest answer when the interviewer asks "what does the wire format look like?"
Strip unpicklable resources (open file handles, network sockets, threading.Lock) in __getstate__ and reconstruct them in __setstate__ — the canonical Python docs example reopens a file and seeks back to self.lineno on restore, which is the exact pattern the interviewer wants for a file-backed resumable iterator.