Interview Q&A / Python

IntermediateIn-depth3 min readUpdated 2 Oct 2026

What is a generator in Python, and how is yield different from return?

SHORT ANSWER

A generator is a function that uses yield to produce values one at a time, pausing after each one and resuming where it left off on the next request. return ends the function and gives back one result, while yield hands out a value and keeps the function's state. Generators save memory because they never build the full list.

Explain it simply

Compare a full thali with a South Indian meal served on a banana leaf. With the thali, everything is cooked and placed on your plate at once, so you need a big plate. On the banana leaf, the server brings one item at a time, only when you are ready for it. The kitchen remembers what it has already served and continues from there.

A normal function that builds a list is the thali: it creates every value up front and returns them all. A generator is the banana leaf server: it gives one value, pauses, and continues only when you ask for the next.

Example

python
def squares_list(n):
    result = []
    for i in range(n):
        result.append(i * i)
    return result              # builds the whole list, then returns once

def squares_gen(n):
    for i in range(n):
        yield i * i            # hands out one value, then pauses here

gen = squares_gen(3)
print(next(gen))   # 0
print(next(gen))   # 1
print(next(gen))   # 4
# next(gen) now raises StopIteration: the generator is finished

for sq in squares_gen(4):
    print(sq)      # 0, 1, 4, 9 on separate lines

total = sum(x * x for x in range(10_000_000))   # generator expression, no huge list
print(total)

How it works

  • Calling a function that contains yield does not run its body. It returns a generator object.
  • Each next() runs the body until the next yield, returns that value, and freezes the function: local variables and the current line are saved.
  • The next next() resumes right after that yield.
  • When the function ends (or hits return), Python raises StopIteration. A for loop catches this for you and stops quietly.
  • A generator can only be used once. After it is exhausted, looping over it again gives nothing.

Generator expressions use round brackets: (x * x for x in data). They are the lazy version of a list comprehension [x * x for x in data].

Real-world use

  • Reading large files: a 5 GB log file read line by line with for line in open(path) (the file object itself is an iterator).
  • Streaming data: processing rows from a database or API page by page, like fetching IRCTC booking records in batches.
  • Pipelines: chaining steps such as read lines, filter errors, parse fields, where each step pulls one item at a time.
  • Infinite sequences: generating ticket numbers or IDs forever without running out of memory.

Common mistakes

  • Looping over the same generator twice and getting nothing the second time.
  • Calling len() on a generator. It has no length; convert it with list() if you really need one.
  • Expecting the function body to run when you call it. Nothing happens until you start iterating.
  • Using a generator when you need random access like items[5]. Use a list for that.

What to say in the interview

"A generator is a function with yield. Calling it returns a generator object, and each time you ask for the next value it runs until the next yield, hands out that value, and pauses with its local state saved. return ends the function for good and gives back one result, while yield can produce many values over time. The main benefit is memory: values are produced lazily, so I can process a huge file or an endless stream without loading it all. The trade-off is that a generator can only be iterated once and does not support indexing or len."

Follow-up questions

  • What is the difference between a list comprehension and a generator expression?
  • What happens if you call next() on an exhausted generator?
  • What does yield from do?
  • How is a generator related to an iterator?

Go deeper

Read these once the basics above feel easy.

Every generator is an iterator: it has __iter__ and __next__. Writing the same thing as a class needs you to store the state yourself and raise StopIteration manually; a generator does all of that for you.

yield from other_iterable delegates to another generator or iterable, yielding each of its values. It is handy for flattening nested structures or splitting a big generator into smaller ones.

Generators can also receive values with gen.send(value), which becomes the result of the yield expression inside. This is how coroutines worked before async/await, though you rarely need it in everyday code.

#python#generators#iterators#memory

Related questions

Practise more Python questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open Python quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.