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.