Python 3 Guide: Basics & Idioms

Minimal foundations for algorithm work. For container cheat sheets, see Python Quick Reference for LeetCode.

Contents

Types & mutability

# Immutable: int, float, bool, str, tuple, frozenset
# Mutable: list, dict, set, bytearray

x = [1, 2, 3]
y = x          # same list object
y.append(4)    # x is also [1, 2, 3, 4]

a = (1, 2, [3])
a[2].append(4) # OK — tuple holds a reference to a mutable list

Truthiness: empty containers and 0 are falsy; use if items: not if len(items) > 0: unless you need the length.

Control flow

for i, x in enumerate(nums):
    if x < 0:
        continue
    if x == target:
        break

for k in range(n):           # 0 .. n-1
    pass

for k in range(1, n + 1):    # 1 .. n
    pass

while lo <= hi:
    mid = (lo + hi) // 2
    lo = mid + 1

for / while / else: the else runs only if the loop did not break (useful for search loops).

Functions

def add(a: int, b: int) -> int:
    return a + b

def greet(name: str = "world") -> None:
    print(f"hello {name}")

# *args / **kwargs
def f(*args, **kwargs):
    pass

Mutable default pitfall — never use a mutable default:

# BAD
def bad(x, memo={}):
    memo[x] = True
    return memo

# GOOD
def good(x, memo=None):
    if memo is None:
        memo = {}
    memo[x] = True
    return memo

Lambdas — fine for sort(key=lambda p: p[1]); prefer def for anything non-trivial.

Comprehensions & unpacking

squares = [x * x for x in range(10)]
evens = [x for x in nums if x % 2 == 0]
matrix = [[0] * cols for _ in range(rows)]   # correct 2D init

# dict / set comprehensions
idx = {v: i for i, v in enumerate(nums)}
unique = {x for x in nums}

# unpacking
first, *rest = nums
a, b = b, a
lo, hi = 0, len(nums) - 1

Classes (sketch)

LeetCode often uses plain functions; classes appear in design problems and DSU:

class Node:
    __slots__ = ("val", "left", "right")  # optional: less memory

    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

@dataclass (3.7+) is handy for small structs:

from dataclasses import dataclass

@dataclass
class Edge:
    to: int
    w: int

Imports

Typical competitive / LeetCode header:

from collections import Counter, defaultdict, deque
from functools import lru_cache
import heapq
import bisect
import math

Import once at the top of your solution file (LeetCode editor allows this).

Common idioms

# frequency
freq = Counter(nums)

# adjacency list
graph = defaultdict(list)
for u, v in edges:
    graph[u].append(v)

# stack as list
st = []
st.append(x)
x = st.pop()

# BFS queue
q = deque([start])

# infinity
INF = 10**18

Interview pitfalls

Pitfall Fix
[[0]*m]*n shared rows [[0]*m for _ in range(n)]
Modifying list while iterating iterate copy or use index
dict key not hashable use tuple or convert key
Deep recursion on large graphs sys.setrecursionlimit or iterative DFS/BFS
heapq is min-heap only negate for max-heap
import sys
sys.setrecursionlimit(10**6)  # deep tree DFS only when needed

More in this guide