enumerate, zip, map, filter
Learn Python's powerful built-in tools that let you process lists and sequences in clean, expressive ways without manual index juggling.
Python ships with a toolbox of built-in functions that make working with lists and sequences much cleaner. Instead of tracking index numbers yourself or writing long loops, these tools let you express what you want, not how to count. The result is shorter, more readable code that experienced Python developers will recognize immediately as "Pythonic".
See it in action
— step through the idea, then dive into the details below.Python's Built-In Power Tools
Python ships with functions like enumerate, zip, map, and filter that make list processing clean and expressive. No more manual index juggling — just tell Python what you want.
#The Problem With Manual Indexing
Have you ever needed to loop over a list but also needed to know the position of each item? The common beginner approach reaches for a counter variable — but Python has a much cleaner way.
# The manual way — works, but clunky
fruits = ["apple", "banana", "cherry"]
i = 0
for fruit in fruits:
print(i, fruit)
i += 1#enumerate() — Index and Value Together
enumerate(sequence) hands you both the index and the value at the same time, wrapped together in a pair. You unpack that pair directly in the for line.
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
print(index, fruit)Start counting from 1
You can tell enumerate to start at a different number: enumerate(fruits, start=1). Great for user-facing numbered lists where humans expect to start at 1, not 0.
fruits = ["apple", "banana", "cherry"]
for number, fruit in enumerate(fruits, start=1):
print(f"{number}. {fruit}")#zip() — Walking Two Lists Together
Imagine you have two separate lists — one of names and one of scores — and you want to pair them up. zip(list_a, list_b) acts like a zipper on a jacket: it brings two separate sides together, tooth by tooth, pair by pair.
names = ["Alice", "Bob", "Carol"]
scores = [95, 82, 78]
for name, score in zip(names, scores):
print(f"{name}: {score}")zip() stops at the shortest list
If your two lists have different lengths, zip() quietly stops when the shorter one runs out. The extra items in the longer list are silently ignored. Always make sure your lists are the same length, or use itertools.zip_longest if you need to handle all items.
#map() — Apply a Function to Every Item
map(function, sequence) applies a function to every item in a list and gives you back the transformed results. Think of it like an assembly line: each item passes through a machine (your function) and comes out changed.
words = ["hello", "world", "python"]
upper_words = list(map(str.upper, words))
print(upper_words)map() is lazy — wrap it in list()
map() does not immediately compute all the results. It waits until you ask for them. Wrapping it in list() forces it to run right now and gives you a plain list you can print and inspect.
For simple transformations, a list comprehension often reads more naturally than map(). Both are correct — choose whichever feels clearer to you and your teammates.
words = ["hello", "world", "python"]
# With map
upper_map = list(map(str.upper, words))
# With a list comprehension — often easier to read
upper_comp = [w.upper() for w in words]
print(upper_map)
print(upper_comp)#filter() — Keep Only What Passes a Test
filter(function, sequence) goes through a list and keeps only the items for which the function returns True. It's like a bouncer at a door — each item must pass the check to get through.
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def is_even(n):
return n % 2 == 0
evens = list(filter(is_even, numbers))
print(evens)Again, a list comprehension with a condition is often more readable for straightforward cases:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [n for n in numbers if n % 2 == 0]
print(evens)#sorted() With a Key
sorted(sequence) returns a new sorted list. The real power comes from the key= argument, which tells Python what to sort by. You pass a function, and Python calls it on each item to get a comparison value.
words = ["banana", "fig", "apple", "kiwi", "elderberry"]
# Sort alphabetically (default)
print(sorted(words))
# Sort by word length
print(sorted(words, key=len))#any(), all(), sum(), min(), max()
These five built-ins summarize an entire sequence in one call. They save you from writing loops just to compute a single yes/no or number.
scores = [72, 85, 91, 60, 88]
print(sum(scores)) # total
print(min(scores)) # lowest
print(max(scores)) # highest
print(any(s >= 90 for s in scores)) # is at least one score >= 90?
print(all(s >= 60 for s in scores)) # are ALL scores >= 60?any() and all() are like voting
Think of any() as "does at least one person raise their hand?" and all() as "does every single person raise their hand?" — any() needs just one True, all() needs every item to be True.
#reversed() — Iterate Backwards
reversed(sequence) lets you loop through a list from last to first without modifying the original. Like map(), it is lazy — wrap it in list() if you want a reversed copy, or just loop over it directly.
countdown = [5, 4, 3, 2, 1]
for n in reversed(countdown):
print(n)#Putting It All Together
students = ["Diana", "Eli", "Fiona", "George"]
grades = [88, 95, 72, 91]
# Pair students with grades, then sort by grade descending
paired = list(zip(students, grades))
ranked = sorted(paired, key=lambda item: item[1], reverse=True)
for rank, (name, grade) in enumerate(ranked, start=1):
print(f"#{rank} {name}: {grade}")
print(f"\nClass average: {sum(grades) / len(grades):.1f}")
print(f"Anyone got 100? {any(g == 100 for g in grades)}")What will this code print? names = ["Ana", "Ben"] scores = [90, 85, 70] for name, score in zip(names, scores): print(name, score)
Key takeaways
- enumerate(seq) gives you index + value pairs so you never need a manual counter variable.
- zip(a, b) pairs two sequences by position — it stops at the shorter one, so keep lengths equal.
- map() and filter() transform or select items; list comprehensions often express the same idea more readably.
- sorted(key=...) lets you sort by any property — just pass a function that extracts the comparison value.
- any(), all(), sum(), min(), and max() collapse a whole sequence into a single answer without an explicit loop.
What does this code print?
fruits = ["apple", "banana", "cherry"]
for number, fruit in enumerate(fruits, start=1):
print(f"{number}. {fruit}")What does this code print?
names = ["Alice", "Bob"]
scores = [95, 82, 70]
for name, score in zip(names, scores):
print(name, score)This code should print only the even numbers, but it prints all of them instead. What is wrong?
numbers = [1, 2, 3, 4, 5, 6]
def is_even(n):
return n % 2 == 0
evens = list(map(is_even, numbers))
print(evens)Complete the code so it prints the total of all scores and then True if any score is 100.
scores = [72, 85, 100, 60] print((scores)) print((s == 100 for s in scores))
You have two lists: products = ["Widget", "Gadget", "Doohickey", "Thingamajig"] and prices = [9.99, 24.50, 4.75, 15.00]. Do the following in order: 1. Print a numbered menu (starting at 1) showing each product and its price. 2. Print only the products that cost more than $10, sorted alphabetically. 3. Print the total cost if someone bought one of everything.
Try it live — edit the code and hit Run to execute real Python: