Implement iter returning an iterator, or generate with a generator method
The for loop calls iter(obj) once and then next() until StopIteration. So you need either iter that returns an iterator, or the legacy getitem protocol that yields values by integer index until IndexError. The cleanest modern approach is to make iter a generator function: writing def iter(self): for item in self._data: yield item turns iter into a generator function, so each call returns a fresh generator. That gives you re-iterability for free and keeps the code short. If your object is itself a one-shot stream, you can implement iter returning self plus next instead.
Prefer a generator-based iter for containers because it is concise and re-iterable.
Implement next plus iter returning self only when the object is inherently a one-shot iterator, such as a socket reader.
getitem with integer indexing still works for the for loop but is legacy; avoid it for new code except for compatibility.
Trade-off: generator iter is easier but hides the iteration logic; an explicit iterator class is more verbose but easier to instrument and reset.
Common mistake: implementing next without iter and then finding that for loops raise TypeError: object is not iterable.
Version note: iter/next is the modern protocol (PEP 234). getitem iteration is a backward-compatibility fallback and is not recommended for new code.
0-2 years experience
2-5 years experience
5-8 years experience
8+ years experience