Python · 01/10 6 min
Python gotchas
Mutable defaults, late binding, shallow copies, and friends.
def add(item, bucket=[]): # ❌ the SAME list is reused across calls
bucket.append(item); return bucket
def add(item, bucket=None): # ✅
bucket = [] if bucket is None else bucket
grid = [[0] * 3] * 3 # ❌ 3 references to one row
grid = [[0] * 3 for _ in range(3)] # ✅
fns = [lambda: i for i in range(3)] # all return 2 (late binding)
fns = [lambda i=i: i for i in range(3)]
7 // 2 == 3; -7 // 2 == -4 # floor division rounds toward -∞
a is b # identity, not equality → use ==
if value: # 0, "", [] are falsy → use 'is not None' when 0 is valid
for k in d: # ❌ RuntimeError if you add/delete keys while iterating
for k in list(d): # ✅
Useful built-ins in DSA
collections.Counter, defaultdict(list), deque (O(1) popleft), heapq (min-heap; push -x for max), bisect, functools.lru_cache for memoised recursion.
Practise it now
Next in Python
Names, mutability and copies