BugForge
All lessons
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.

Next in Python
Names, mutability and copies