A list comprehension builds a new list from an existing one in a single line — this is one of the most distinctly "Python" features in the language, and real Python code uses it constantly.
Here's the same task — squaring every number in a list — written both ways:
# The long way, with a regular loop:
numbers = [1, 2, 3, 4, 5]
squared = []
for n in numbers:
squared.append(n ** 2)
print(squared) # [1, 4, 9, 16, 25]
# The same thing, as a list comprehension:
squared = [n ** 2 for n in numbers]
print(squared) # [1, 4, 9, 16, 25]The pattern is [expression for item in iterable] — read it left to right as "the result of expression, for every item in iterable."
An optional if at the end filters which items get included — this is the comprehension equivalent of PHP's array_filter() combined with array_map(), in one expression:
numbers = [1, 2, 3, 4, 5, 6]
even_squared = [n ** 2 for n in numbers if n % 2 == 0]
print(even_squared) # [4, 16, 36]The same idea works for building a dictionary, using { } and a key: value pair instead:
names = ["priya", "amit", "sara"]
capitalized = {name: name.capitalize() for name in names}
print(capitalized) # {'priya': 'Priya', 'amit': 'Amit', 'sara': 'Sara'}When not to use one
A comprehension is a readability win for a short, simple transformation. Once the logic inside it gets complicated — several conditions, nested loops, a multi-line transformation — a regular for loop is usually clearer. There's no rule for exactly where that line is; if you find yourself squinting at a comprehension to understand it, that's the signal to write it as a loop instead.