Python Coding Interview Cheat Sheet — Complete Syntax & STL Guide
A practical, no-fluff guide to the Python syntax, built-ins, and idioms you’ll reach for most during a technical interview.
Why Python for Coding Interviews?
If you have the choice, Python is arguably the best language for technical interviews. Here is why:
- Concise Syntax: You have 45 minutes to solve a problem. Python’s lack of boilerplate (no semicolons, brackets, or strict typing) means you spend less time typing and more time thinking and communicating.
- Rich Standard Library: Built-in tools like
collections.Counter,defaultdict,heapq, andbisectallow you to implement complex logic in a single line. - No Integer Overflow: Python handles arbitrarily large integers automatically, eliminating a whole class of edge-case calculation bugs that plague C++ and Java candidates.
- Reads Like Pseudocode: Python’s English-like structure makes it incredibly easy for interviewers to follow your logic when you are explaining your approach out loud.
If you're building your full preparation plan, start with our How to Prepare for a Coding Interview guide. This also pairs perfectly with Data Structures for Coding Interviews and the Python Data Structures Implementation Guide.
Looking for a different language? Java, C++, JavaScript, Go.
Already know why Python? Try a free Python mock interview on Intervu →
1. Data Types & Variables
# Integers (arbitrary precision — no overflow in Python!)
x = 10
big = 10 ** 18 # Works perfectly
# Float
pi = 3.14159
# Boolean
flag = True # Capitalized! True / False
# None
val = None
# Type checking
type(x) # <class 'int'>
isinstance(x, int) # True
# Multiple assignment
a, b, c = 1, 2, 3
a, b = b, a # Swap in one line
# Infinity
INF = float('inf')
NEG_INF = float('-inf')
Key tip: Python integers never overflow, which eliminates an entire class of bugs common in Java/C++. You can use 10 ** 18 freely as a stand-in for infinity in many problems.
2. Strings
Strings come up in nearly every Python coding interview — from anagram checks to parsing problems.
s = "hello world"
# Basics
len(s) # 11
s[0] # 'h'
s[-1] # 'd'
s[1:5] # 'ello'
s[::-1] # 'dlrow olleh' (reverse)
# Methods
s.upper() # 'HELLO WORLD'
s.lower() # 'hello world'
s.strip() # removes leading/trailing whitespace
s.split() # ['hello', 'world']
s.split(',') # split by delimiter
','.join(['a','b','c']) # 'a,b,c'
s.replace('l', 'r') # 'herro worrd'
s.startswith('he') # True
s.endswith('ld') # True
s.find('world') # 6 (-1 if not found)
s.index('world') # 6 (raises ValueError if not found!)
s.count('l') # 3
# Check character types
'abc'.isalpha() # True
'123'.isdigit() # True
'abc123'.isalnum() # True
# String → list of chars and back
chars = list(s)
''.join(chars) # back to string
# Ord / Chr — useful for encoding tricks
ord('a') # 97
chr(97) # 'a'
ord('z') - ord('a') # 25
# f-strings (preferred for formatting)
name, score = "Alice", 42
f"{name} scored {score} points" # 'Alice scored 42 points'
Key tip: Strings are immutable in Python. To build a string incrementally, collect characters in a list and ''.join() at the end — O(n) vs O(n²) for repeated +=. Also: s[0] = 'X' raises a TypeError — a common gotcha for C++/Java candidates.
3. Lists
Lists are Python’s workhorse data structure in coding interviews. Know these operations cold.
lst = [3, 1, 4, 1, 5, 9]
# Access & slicing
lst[0] # 3
lst[-1] # 9
lst[1:4] # [1, 4, 1]
lst[::-1] # reversed copy
# Modify
lst.append(2) # add to end — O(1)
lst.insert(0, 99) # insert at index — O(n)
lst.pop() # remove & return last — O(1)
lst.pop(0) # remove & return first — O(n)
lst.remove(4) # remove first occurrence of value
del lst[2] # delete by index
# Info
len(lst) # length
lst.count(1) # count occurrences
lst.index(5) # first index of value
# Sort (in-place)
lst.sort() # ascending
lst.sort(reverse=True) # descending
# Sorted (returns new list)
sorted(lst)
sorted(lst, reverse=True)
sorted(lst, key=lambda x: -x)
# Initialize
zeros = [0] * 10 # [0, 0, 0, ..., 0]
matrix = [[0] * cols for _ in range(rows)] # 2D — use comprehension!
# Flatten
nested = [[1,2],[3,4]]
flat = [x for row in nested for x in row]
# Stack (use list as stack)
stack = []
stack.append(val) # push
stack.pop() # pop
# Queue (use deque, not list)
from collections import deque
q = deque()
q.append(val) # enqueue right
q.popleft() # dequeue left — O(1)
Key tip: Never use a plain list as a queue — list.pop(0) is O(n). Always use collections.deque for O(1) left-side operations.
4. Tuples & Sets
# Tuple — immutable, hashable (can be dict key or set element)
t = (1, 2, 3)
a, b, c = t # unpack
t[0] # 1
# Set — unordered, unique elements, O(1) average lookup
s = {1, 2, 3, 3} # {1, 2, 3}
s.add(4)
s.remove(2) # KeyError if missing
s.discard(99) # safe remove
2 in s # True — O(1)
# Set operations
a = {1, 2, 3}
b = {2, 3, 4}
a | b # union {1, 2, 3, 4}
a & b # intersection {2, 3}
a - b # difference {1}
a ^ b # symmetric diff {1, 4}
# Frozenset — immutable set (hashable)
fs = frozenset([1, 2, 3])
Key tip: Sets are unordered — unlike dict (which preserves insertion order since Python 3.7), sets give no guarantees on iteration order. Don’t rely on list(my_set) being ordered.
5. Dictionaries
Dictionaries are the most versatile structure in Python coding interviews — frequency maps, adjacency lists, memos, and more.
d = {'a': 1, 'b': 2}
# Access
d['a'] # 1
d.get('z') # None (no KeyError)
d.get('z', 0) # 0 (default value)
# Modify
d['c'] = 3 # add/update
del d['a'] # delete key
d.pop('b') # remove and return value
d.pop('x', None) # safe pop with default
# Info
len(d) # number of keys
'a' in d # True — O(1)
d.keys() # dict_keys view
d.values() # dict_values view
d.items() # dict_items view — use in loops!
# Iterating
for k, v in d.items():
print(k, v)
# Merge (Python 3.9+)
merged = d1 | d2
# Default dict pattern (manual)
counts = {}
for char in "hello":
counts[char] = counts.get(char, 0) + 1
# setdefault
graph = {}
graph.setdefault('A', []).append('B')
6. Control Flow
# if / elif / else
if x > 0:
pass
elif x == 0:
pass
else:
pass
# Ternary
result = "pos" if x > 0 else "non-pos"
# for loop
for i in range(5): # 0, 1, 2, 3, 4
pass
for i in range(2, 10, 2): # 2, 4, 6, 8
pass
for i in range(9, -1, -1): # 9 down to 0
pass
# enumerate
for i, val in enumerate(lst):
pass
for i, val in enumerate(lst, start=1): # start index at 1
pass
# zip
for a, b in zip(list1, list2):
pass
# while
while condition:
pass
# break / continue / else on loops
for i in range(10):
if i == 5:
break
else:
# runs only if loop didn't break
pass
7. Functions
# Basic
def add(a, b):
return a + b
# Default args
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
# *args and **kwargs
def f(*args, **kwargs):
print(args) # tuple
print(kwargs) # dict
# Lambda
square = lambda x: x * x
# Multiple return values (returns tuple)
def min_max(lst):
return min(lst), max(lst)
lo, hi = min_max([3, 1, 4])
# Nested functions / closures
def outer(x):
def inner(y):
return x + y
return inner
add5 = outer(5)
add5(3) # 8
# nonlocal — modify an outer (non-global) variable from a nested function
def solve():
count = 0
def dfs(node):
nonlocal count # REQUIRED — without this, count += 1 raises UnboundLocalError
count += 1
dfs(root)
return count
# global — rarely needed in interviews, but good to know
total = 0
def add(x):
global total
total += x
# Recursion limit — Python default is 1000; increase for deep DFS / backtracking
import sys
sys.setrecursionlimit(10**6)
Key tip: nonlocal is one of the most common Python interview gotchas. Any nested function that modifies (not just reads) an outer variable needs nonlocal, or you’ll get an UnboundLocalError.
8. List Comprehensions & Generators
List comprehensions are a hallmark of idiomatic Python — interviewers appreciate seeing them used correctly.
# List comprehension
squares = [x**2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
# Nested
matrix = [[i*j for j in range(3)] for i in range(3)]
# Dict comprehension
word_len = {w: len(w) for w in ["apple", "banana"]}
# Set comprehension
unique_lens = {len(w) for w in ["hi", "hey", "hello"]}
# Generator expression (memory-efficient)
total = sum(x**2 for x in range(1000000)) # no list created
# any / all with generators
any(x > 5 for x in lst) # True if at least one
all(x > 0 for x in lst) # True if all
9. Sorting
lst = [3, 1, 4, 1, 5]
# Built-ins
lst.sort() # in-place
sorted_lst = sorted(lst) # returns new list
# Custom key
words = ["banana", "fig", "apple", "kiwi"]
words.sort(key=len) # by length
words.sort(key=lambda w: w[-1]) # by last character
# Sort tuples by second element
pairs = [(1, 3), (2, 1), (3, 2)]
pairs.sort(key=lambda x: x[1])
# Sort by multiple criteria
data.sort(key=lambda x: (x[1], -x[0])) # by second asc, first desc
# Reverse
lst.sort(reverse=True)
sorted(lst, reverse=True)
# Max/Min with key
max(words, key=len) # longest word
min(pairs, key=lambda x: x[1])
10. Collections Module
The collections module is one of the most useful tools in a Python coding interview. Learn Counter, defaultdict, and deque thoroughly.
from collections import Counter, defaultdict, deque
# Counter — frequency map
c = Counter("abracadabra")
# Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
c.most_common(3) # [('a', 5), ('b', 2), ('r', 2)]
c['a'] # 5
c['z'] # 0 (no KeyError!)
c1 = Counter("hello")
c2 = Counter("world")
c1 + c2 # combine counts
c1 - c2 # subtract counts
c1 & c2 # intersection (min of each)
c1 | c2 # union (max of each)
# defaultdict — never get a KeyError for missing keys
graph = defaultdict(list)
graph['A'].append('B') # no initialization needed
word_count = defaultdict(int)
for w in words:
word_count[w] += 1
nested = defaultdict(lambda: defaultdict(int))
# deque — efficient double-ended queue
dq = deque([1, 2, 3])
dq.append(4) # right end
dq.appendleft(0) # left end — O(1)
dq.pop() # right end
dq.popleft() # left end — O(1)
dq.rotate(1) # rotate right
deque(lst, maxlen=k) # sliding window of size k
Key tip: Add OrderedDict for LRU Cache problems — it natively supports move_to_end() and popitem(last=False) for O(1) eviction.
from collections import OrderedDict
cache = OrderedDict()
cache[key] = value
cache.move_to_end(key) # mark as most recently used
cache.popitem(last=False) # evict least recently used (leftmost)
11. Heapq Module
Python’s heapq implements a min-heap. It’s the go-to for problems involving the k-th largest/smallest element, priority queues, or Dijkstra’s algorithm.
import heapq
# Min-heap
heap = [3, 1, 4, 1, 5]
heapq.heapify(heap) # in-place, O(n)
heapq.heappush(heap, 2) # O(log n)
heapq.heappop(heap) # pops smallest, O(log n)
heap[0] # peek min without popping
heapq.nsmallest(3, lst) # 3 smallest elements
heapq.nlargest(3, lst) # 3 largest elements
# Max-heap trick: negate values
max_heap = []
heapq.heappush(max_heap, -val)
max_val = -heapq.heappop(max_heap)
# Heap of tuples (sorted by first element)
heapq.heappush(heap, (priority, item))
# Push then pop (more efficient)
heapq.heappushpop(heap, val) # push val, pop min (checks val vs min first)
heapq.heapreplace(heap, val) # pop min, push val (raises IndexError on empty heap!)
# Tie-breaker for heaps with non-comparable items (e.g. TreeNode)
import itertools
_counter = itertools.count()
heapq.heappush(heap, (priority, next(_counter), item)) # counter breaks ties
Key tip: Prefer heappushpop over separate push+pop — it’s a single heap operation. Use the tie-breaker counter whenever your heap items aren’t directly comparable (e.g., custom objects).
12. Binary Search with bisect
import bisect
lst = [1, 3, 5, 7, 9] # must be sorted
# Find insertion point
bisect.bisect_left(lst, 5) # 2 (leftmost index where 5 can be inserted; also the index of 5 if it exists)
bisect.bisect_right(lst, 5) # 3 (rightmost position to insert 5)
bisect.bisect(lst, 5) # same as bisect_right
# Insert while keeping sorted
bisect.insort_left(lst, 6)
bisect.insort_right(lst, 6)
# Count occurrences in sorted list
def count_of(lst, val):
return bisect.bisect_right(lst, val) - bisect.bisect_left(lst, val)
# Find floor/ceiling
def floor(lst, val):
i = bisect.bisect_right(lst, val) - 1
return lst[i] if i >= 0 else None
def ceiling(lst, val):
i = bisect.bisect_left(lst, val)
return lst[i] if i < len(lst) else None
13. Itertools
import itertools
# Combinations & Permutations
list(itertools.combinations([1,2,3], 2))
# [(1,2), (1,3), (2,3)]
list(itertools.permutations([1,2,3], 2))
# [(1,2), (1,3), (2,1), (2,3), (3,1), (3,2)]
list(itertools.combinations_with_replacement([1,2,3], 2))
# [(1,1), (1,2), (1,3), (2,2), (2,3), (3,3)]
# Product (cartesian product)
list(itertools.product([0,1], repeat=3))
# all 3-bit binary strings
# Chain — flatten iterables
list(itertools.chain([1,2], [3,4], [5]))
# [1, 2, 3, 4, 5]
# Accumulate — running totals
list(itertools.accumulate([1,2,3,4]))
# [1, 3, 6, 10]
import operator
list(itertools.accumulate([1,2,3,4], operator.mul))
# [1, 2, 6, 24] (running product)
# groupby — group consecutive equal elements (sort first!)
data = sorted(people, key=lambda p: p['dept'])
for dept, members in itertools.groupby(data, key=lambda p: p['dept']):
print(dept, list(members))
# zip_longest — zip unequal-length iterables (fills missing with fillvalue)
from itertools import zip_longest
for a, b in zip_longest(list1, list2, fillvalue=0):
pass # useful for Add Two Numbers, merging lists of different lengths
14. Math & Numbers
import math
# Common constants
math.pi # 3.14159...
math.e # 2.71828...
math.inf # infinity
float('inf') # same
# Common functions
math.sqrt(16) # 4.0
math.floor(3.7) # 3
math.ceil(3.2) # 4
math.log(8, 2) # 3.0 (log base 2)
math.log2(8) # 3.0
math.log10(100) # 2.0
math.gcd(12, 8) # 4
math.lcm(4, 6) # 12 (Python 3.9+)
math.factorial(5) # 120
math.isqrt(17) # 4 (integer square root)
abs(-5) # 5
# Bit operations
x & y # AND
x | y # OR
x ^ y # XOR
~x # NOT
x << 1 # left shift (×2)
x >> 1 # right shift (÷2)
x.bit_length() # number of bits needed
bin(10) # '0b1010'
int('1010', 2) # 10 (binary string → int)
# Common bit manipulation patterns (very frequent in interviews!)
n & (n - 1) == 0 # True if n is a power of 2 (and n > 0)
n & (-n) # isolate the lowest set bit
bin(n).count('1') # count set bits (popcount)
n.bit_count() # same, Python 3.10+
from functools import reduce
reduce(lambda a, b: a ^ b, nums) # XOR all elements — find the unique number
# Modular arithmetic
pow(base, exp, mod) # fast modular exponentiation — built-in!
15. I/O & String Formatting
# Input (always returns string)
line = input()
n = int(input())
a, b = map(int, input().split())
lst = list(map(int, input().split()))
# Read multiple lines
import sys
data = sys.stdin.read().split()
# Print
print("hello", "world") # space-separated by default
print("hello", "world", sep=",") # 'hello,world'
print("hello", end="") # no newline
# f-strings
f"{value:.2f}" # 2 decimal places
f"{value:05d}" # zero-padded to width 5
f"{value:>10}" # right-align in width 10
f"{value:b}" # binary representation
f"{value:,}" # thousand separators
16. Common Algorithm Patterns
These are the patterns that appear in the vast majority of Python coding interview questions. Memorize the templates, then practice applying them.
Two Pointers
def two_sum_sorted(arr, target):
l, r = 0, len(arr) - 1
while l < r:
s = arr[l] + arr[r]
if s == target:
return [l, r]
elif s < target:
l += 1
else:
r -= 1
Sliding Window
def max_sum_subarray(arr, k):
window = sum(arr[:k])
best = window
for i in range(k, len(arr)):
window += arr[i] - arr[i - k]
best = max(best, window)
return best
Fast & Slow Pointers (Floyd’s Cycle Detection)
def has_cycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
BFS Template
from collections import deque
def bfs(graph, start):
visited = set([start])
queue = deque([start])
while queue:
node = queue.popleft()
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
DFS Template (Iterative)
def dfs(graph, start):
visited = set()
stack = [start]
while stack:
node = stack.pop()
if node not in visited:
visited.add(node)
stack.extend(graph[node])
DFS Template (Recursive)
def dfs(node, visited):
visited.add(node)
for neighbor in graph[node]:
if neighbor not in visited:
dfs(neighbor, visited)
Binary Search Template
def binary_search(arr, target):
lo, hi = 0, len(arr) - 1
while lo <= hi:
mid = lo + (hi - lo) // 2 # Python can't overflow, but this is a good habit from C++/Java
if arr[mid] == target:
return mid
elif arr[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1 # or lo for insertion point
Dynamic Programming — Memoization
from functools import lru_cache, cache
# Classic: lru_cache with unlimited size
@lru_cache(maxsize=None)
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
# Shorthand (Python 3.9+) — identical behavior, cleaner
@cache
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
# Or use a dict manually
memo = {}
def dp(state):
if state in memo:
return memo[state]
# ... compute result
memo[state] = result
return result
Prefix Sum
def prefix_sum(arr):
prefix = [0] * (len(arr) + 1)
for i, val in enumerate(arr):
prefix[i+1] = prefix[i] + val
return prefix
# Range sum query: sum(arr[l:r+1]) = prefix[r+1] - prefix[l]
Monotonic Stack
def next_greater(arr):
n = len(arr)
result = [-1] * n
stack = [] # stores indices
for i in range(n):
while stack and arr[i] > arr[stack[-1]]:
result[stack.pop()] = arr[i]
stack.append(i)
return result
Unpacking & Enumerate Tricks
# Swap
a, b = b, a
# Unpack first and rest
first, *rest = [1, 2, 3, 4]
# Unpack last
*init, last = [1, 2, 3, 4]
# Iterate with index and value
for i, (x, y) in enumerate(pairs):
pass
# Zip with index
for i, (a, b) in enumerate(zip(list1, list2)):
pass
Standard Node Definitions
Many LeetCode problems use these classes. When they’re not pre-defined, write them from memory:
# Binary tree node
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
# Singly linked list node
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
Building a Graph from an Edge List
BFS/DFS templates assume graph[node] exists — here’s how to actually build it:
from collections import defaultdict
# Undirected graph from edge list
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u) # omit this line for directed graphs
# Weighted graph
for u, v, w in edges:
graph[u].append((v, w))
graph[v].append((u, w))
Backtracking Template
Use for subsets, permutations, combinations, N-Queens, and word search:
result = []
def backtrack(start, path):
result.append(path[:]) # record a valid state
for i in range(start, len(nums)):
path.append(nums[i]) # choose
backtrack(i + 1, path) # explore (use i instead of i+1 for repetition allowed)
path.pop() # undo (backtrack)
backtrack(0, [])
Key tip: The path.pop() at the end is what makes it backtracking — always undo the last choice before the next iteration.
Union-Find (Disjoint Set Union)
Essential for graph connectivity problems (Number of Connected Components, Redundant Connection, etc.):
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0] * n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x]) # path compression
return self.parent[x]
def union(self, x, y):
px, py = self.find(x), self.find(y)
if px == py:
return False # already connected
if self.rank[px] < self.rank[py]:
px, py = py, px
self.parent[py] = px
if self.rank[px] == self.rank[py]:
self.rank[px] += 1
return True
uf = UnionFind(n)
uf.union(0, 1)
uf.find(1) # returns root of component
Trie (Prefix Tree)
Used for word search, autocomplete, and prefix-matching problems:
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for ch in word:
if ch not in node.children:
node.children[ch] = TrieNode()
node = node.children[ch]
node.is_end = True
def search(self, word):
node = self.root
for ch in word:
if ch not in node.children:
return False
node = node.children[ch]
return node.is_end
def starts_with(self, prefix):
node = self.root
for ch in prefix:
if ch not in node.children:
return False
node = node.children[ch]
return True
Quick Reference Cheat Sheet
| Task | Snippet |
|---|---|
| Reverse a list | lst[::-1] |
| Sort by custom key | sorted(lst, key=lambda x: ...) |
| Count characters | Counter(s) |
| Group adjacents | itertools.groupby(sorted_lst, key) |
| Flatten list | [x for row in matrix for x in row] |
| Default dict | defaultdict(list) / defaultdict(int) |
| Min/Max heap | heapq.heapify(lst) / negate for max-heap |
| Binary search | bisect.bisect_left(lst, val) |
| Memoize recursive | @cache (Python 3.9+) or @lru_cache(maxsize=None) |
| Infinity | float('inf') |
| Swap | a, b = b, a |
| Check all same | len(set(lst)) == 1 |
| Running sum | itertools.accumulate(lst) |
| Fast mod exp | pow(base, exp, mod) |
| Power of 2 check | n > 0 and n & (n - 1) == 0 |
| XOR all elements | reduce(lambda a, b: a ^ b, nums) |
| Count set bits | bin(n).count('1') or n.bit_count() (3.10+) |
| Zip unequal lists | zip_longest(a, b, fillvalue=0) |
| Modify outer var | nonlocal count inside nested function |
| Allow deep recursion | sys.setrecursionlimit(10**6) |
| LRU cache eviction | OrderedDict + move_to_end() + popitem(last=False) |
| Build graph | defaultdict(list) + iterate edges |
Related Interview Topics
Comfortable with Python syntax? The next step is mastering how to apply these tools to the most common interview problem categories:
- Arrays & Hashing — frequency maps, two-sum variants, sliding window
- Binary Search — search on sorted arrays, binary search on answer
- Trees & Graphs — BFS/DFS, topological sort, shortest path
- Dynamic Programming — memoization, tabulation, classic DP patterns
- Heaps & Priority Queues — k-th largest, merge k sorted lists
Each of these patterns has dedicated walkthroughs on the Intervu blog. For a structured problem list, see the Grind 75 Practice Pathway or the comprehensive Data Structures for Coding Interviews guide.
Practice Under Real Interview Conditions
Reading a Python coding interview cheat sheet is a great start — but it’s very different from applying this knowledge when the clock is ticking and an interviewer is watching.
The best way to close that gap is deliberate practice under realistic conditions. Intervu offers AI-powered mock coding interviews that simulate the pressure of a real technical screen — complete with follow-up questions, time limits, and instant feedback on your approach, not just your code.
Ready to test yourself? Start a free mock interview on Intervu →