enumerate, zip & Unpacking Interview Questions & Answers

5 questions Updated 2026-06-18

Python interview questions on enumerate with start, zip and zip_longest, unzipping with zip(*), extended iterable unpacking, and star-args at the call site.

enumerate(iterable) pairs each item with a running index, yielding (index, value) tuples. It saves you from the error-prone manual counter or range(len(...)) pattern. The optional start argument sets the first index (default 0).

colors = ["red", "green", "blue"]

for i, c in enumerate(colors):
    print(i, c)            # 0 red / 1 green / 2 blue

for rank, c in enumerate(colors, start=1):
    print(rank, c)         # 1 red / 2 green / 3 blue

Prefer enumerate over range(len(seq)) whenever you need both the index and the item — it's more readable and works on any iterable, not just indexable sequences.

zip(a, b, ...) walks several iterables in parallel, yielding tuples of aligned elements. It stops at the shortest input, silently dropping extras. itertools.zip_longest instead runs to the longest, filling missing slots with a fillvalue.

names = ["ada", "grace", "edsger"]
ages  = [36, 45]

list(zip(names, ages))     # [('ada', 36), ('grace', 45)]  — 'edsger' dropped

from itertools import zip_longest
list(zip_longest(names, ages, fillvalue=0))
# [('ada', 36), ('grace', 45), ('edsger', 0)]

Use plain zip when lengths match (or truncation is intended); reach for zip_longest when you must not lose data from the longer iterable.

zip is its own inverse. Applying zip(*pairs) unpacks the list of tuples as separate arguments, so zip re-groups them column-wise — effectively transposing rows into columns.

pairs = [("ada", 36), ("grace", 45)]

names, ages = zip(*pairs)
names    # ('ada', 'grace')
ages     # (36, 45)

This also transposes a matrix: list(zip(*matrix)). Note the results are tuples, not lists, and the input is consumed if it's an iterator — wrap in list(...) if you need list results.

A starred target in an assignment captures "the rest" as a list. You can place *name at the start, middle, or end, and the non-starred names take fixed positions — Python figures out the split.

first, *rest = [1, 2, 3, 4]      # first=1, rest=[2, 3, 4]
*init, last = [1, 2, 3, 4]       # init=[1, 2, 3], last=4
head, *mid, tail = [1, 2, 3, 4]  # head=1, mid=[2, 3], tail=4

Exactly one starred target is allowed per assignment, and it always becomes a list (even if empty). This is cleaner than slicing for grabbing the head/tail of a sequence.

Pairing two sequences with zip and feeding them to dict() is the idiomatic way to build a mapping. The * and ** operators also unpack iterables/dicts into function calls as positional and keyword arguments.

keys = ["x", "y", "z"]
vals = [1, 2, 3]
d = dict(zip(keys, vals))        # {'x': 1, 'y': 2, 'z': 3}

def point(x, y, z): return (x, y, z)
args = [1, 2, 3]
point(*args)                     # unpack list -> positional
point(**d)                       # unpack dict -> keyword args

Use * to spread a sequence into positional parameters and ** to spread a dict into keyword parameters — the call-site mirror of *args/**kwargs in a function signature.

Practice tests are coming soon

Get notified when interactive mock interviews and quizzes launch.