📖 11 min read
Last updated on

Python Refresher for Coding Interviews


A practical, no-fluff guide to the Python syntax, built-ins, and idioms you’ll reach for most during a technical interview.

If you’re building your full preparation plan, start with our How to Prepare for a Coding Interview guide. This syntax refresher also pairs perfectly with our Data Structures for Coding Interviews guide and its companion, the Python Data Structures Implementation Guide.

Want to test your Python fluency under real interview pressure? Try a mock coding interview on Intervu →

Stick figure confidently riding a giant Python snake like a cowboy

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, and bisect allow 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.

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 removes an entire class of bugs common in Java/C++.


2. Strings

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.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 +=.


3. Lists

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.


4. Tuples & Sets

Stick figure bouncer denying entry to a duplicate person at a VIP club
# Tuple — immutable, hashable (can be dict key or set element)
t = (1, 2, 3)
a, b, c = t              # unpack
t[0]                     # 1
len(t)                   # 3

# 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])

5. Dictionaries

Stick figure pulling a letter out of a massive wall of tiny mailboxes
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

8. List Comprehensions & Generators

# 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

Stick figure exhausted from sorting giant heavy blocks by height
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

from collections import Counter, defaultdict, deque, OrderedDict

# 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 need to initialize

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

11. Heapq Module

Python’s heapq is a min-heap by default.

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
heapq.heapreplace(heap, val)     # pop min, push val

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 position to insert 5)
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
data = sorted(people, key=lambda p: p['dept'])
for dept, members in itertools.groupby(data, key=lambda p: p['dept']):
    print(dept, list(members))

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)

# Modular arithmetic
pow(base, exp, mod)   # fast modular exponentiation

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 Patterns & Idioms

Two stick figures on opposite ends of a very long dining table sliding their chairs towards each other

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   # avoids overflow (good habit)
        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

@lru_cache(maxsize=None)
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]

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

Quick Reference Cheat Sheet

TaskSnippet
Reverse a listlst[::-1]
Sort by custom keysorted(lst, key=lambda x: ...)
Count charactersCounter(s)
Group adjacentsitertools.groupby(sorted_lst, key)
Flatten list[x for row in matrix for x in row]
Default dictdefaultdict(list) / defaultdict(int)
Min/Max heapheapq.heapify(lst) / negate for max
Binary searchbisect.bisect_left(lst, val)
Memoize recursive@lru_cache(maxsize=None)
Infinityfloat('inf')
Swapa, b = b, a
Check all samelen(set(lst)) == 1
Running sumitertools.accumulate(lst)

Good luck with your interviews! The best way to internalize these is to use them in actual problems — not just read through them. Pick a pattern, find 3 problems that use it, and code them up from scratch.

Practice Like It's the Real Interview

Get instant feedback on your approach, communication, and code — powered by AI.

Start a Mock Interview →