Questions
1 of 19
1How would you make a custom class usable in a for loop?
2How do __enter__ and __exit__ work together to implement the context manager protocol?
3How does Python implement inheritance, and what is the Method Resolution Order (MRO)?
4What are dataclasses, and how do they reduce boilerplate compared to manually writing __init__, __eq__, and __repr__?
5What is the @property decorator, and what problem does it solve compared to plain getter/setter methods?
6What is the difference between method overriding and method overloading, and why doesn't Python natively support overloading?
7What problem does the diamond inheritance pattern cause, and how does Python's MRO resolve it?
8What is the difference between a class and an instance in Python?
9How does Python implement encapsulation given that it has no true 'private' access modifiers?
10What is the purpose of self in instance methods, and why must it be explicitly declared in Python?
11What is the difference between __str__ and __repr__, and what convention should __repr__ follow?
12What is a metaclass, and what is type's relationship to every class in Python?
13What is the purpose of __eq__ and __hash__, and why must they be implemented consistently?
14What is a descriptor, and how do @property and ORMs like Django's models rely on the descriptor protocol?
15What is the difference between an instance method, a class method, and a static method?
16What is composition, and why is 'favor composition over inheritance' often recommended?
17What are dunder (magic) methods, and how do they enable operator overloading?
18When would you use a metaclass instead of a class decorator or __init_subclass__?
19How do abstract base classes (abc.ABC) enforce interface contracts in Python?
01 / 19

How would you make a custom class usable in a for loop?

Difficulty: 5/10
Iteration, Dunder Methods, Generators

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.

  1. 1

    Prefer a generator-based iter for containers because it is concise and re-iterable.

  2. 2

    Implement next plus iter returning self only when the object is inherently a one-shot iterator, such as a socket reader.

  3. 3

    getitem with integer indexing still works for the for loop but is legacy; avoid it for new code except for compatibility.

  4. 4

    Trade-off: generator iter is easier but hides the iteration logic; an explicit iterator class is more verbose but easier to instrument and reset.

  5. 5

    Common mistake: implementing next without iter and then finding that for loops raise TypeError: object is not iterable.

  6. 6

    Version note: iter/next is the modern protocol (PEP 234). getitem iteration is a backward-compatibility fallback and is not recommended for new code.

javascript

Scenario Questions

0-2 years experience

  1. 1You implement __next__ but not __iter__ and for loops fail. Why?
  2. 2What two methods does the iterator protocol require?

2-5 years experience

  1. 1You need a class that can be iterated twice independently. How do you implement it?
  2. 2Your class wraps a file-like reader and should be iterated only once. Which pattern applies?

5-8 years experience

  1. 1You need iteration that supports early exit and cleanup of an external resource. How do you structure __iter__?
  2. 2You are building a paginated client where each page is fetched lazily. How do __iter__ and pagination interact?

8+ years experience

  1. 1Design a class that supports iteration, indexing, slicing, membership testing, and reversed() with minimal dunder implementation.
  2. 2Explain how generator-based __iter__ interacts with context managers and close() when the consumer abandons iteration early.

Follow-up Questions

  • When would returning self from __iter__ be correct rather than a bug?
  • How does the legacy __getitem__ protocol decide when to stop iterating?
Share

Share via WhatsApp, X, Facebook, LinkedIn or copy link. Open Graph preview enabled.