Lists, dicts and comprehensions
Slicing, mutability gotchas, comprehension syntax, and choosing the right collection for the job.
Lists
nums = [3, 1, 2]
nums.append(4) # [3, 1, 2, 4]
nums.extend([5, 6])
nums.insert(0, 0)
last = nums.pop() # removes and returns the last item
nums.sort() # in place; sorted(nums) returns a copy
first, *rest = nums # unpacking| Operation | Cost |
|---|---|
| Index / append / pop from end | O(1) |
| Insert or delete at the front | O(n) — use deque |
x in list | O(n) — use a set for repeated checks |
The aliasing trap
Assignment copies the reference, so two names can point at one list. The classic bug is a default mutable argument, which is evaluated once at definition time and shared by every call.
a = [1, 2]
b = a
b.append(3)
print(a) # [1, 2, 3] - same object
b = a[:] # shallow copy
b = list(a)
# wrong: the default list is shared between calls
def add(item, bucket=[]):
bucket.append(item)
return bucket
# right
def add(item, bucket=None):
bucket = bucket if bucket is not None else []
bucket.append(item)
return bucket⚠️
[[0]] * 3 creates three references to the same inner list — changing one changes all. Use a comprehension: [[0] for _ in range(3)].Comprehensions
squares = [n * n for n in range(10)]
evens = [n for n in nums if n % 2 == 0]
# dict comprehension
by_id = {u['id']: u for u in users}
# conditional transformation
labels = ['even' if n % 2 == 0 else 'odd' for n in nums]
# set comprehension - deduplicates
unique_tags = {t.lower() for t in tags}Read them right to left: the expression first, then the loop, then the filter. If a comprehension needs more than one condition or a nested loop, a plain for block is clearer.
Dicts
user = {'id': 1, 'name': 'Ada'}
user.get('email') # None instead of KeyError
user.get('email', 'n/a') # with default
user.setdefault('role', 'guest')
for key, value in user.items():
print(key, value)
merged = {**user, 'role': 'admin'} # Python 3.5+
counts = dict(Counter(words)) # tallying done for you💡
Dicts preserve insertion order (guaranteed since 3.7), so you rarely need
OrderedDict anymore. Use collections.defaultdict when building groups.FAQ
tuple or list?
Lists for homogeneous sequences that change size; tuples for fixed-shape records (coordinates, return values). Tuples are also hashable, so they work as dict keys.
Why is my loop skipping items while removing?
Mutating a list while iterating it shifts subsequent indices. Iterate over a copy (
for x in list[:]) or build a new list with a comprehension.Related
Python: getting started Functions and modules
Last refreshed 2026-09-17.