Basic Built-in Functions and Libraries#
Python's standard library is large enough to solve most interview problems without third-party packages. Knowing the right built-in or collections helper — and when to reach for it vs rolling your own — saves time and signals idiomatic fluency.
How to use this page
Skim once, then use as a reference before mocks. Setup: The Python Environment. Collections: Data Structures.
At a glance
| Track | Python Basics |
| Sections | 12 major topics |
| Outline | Use the right-hand TOC to jump |
Topics: Built-in functions — complete interview reference · collections module — deep dive · heapq — min-heap on lists · bisect — sorted list operations · itertools — combinatorial iteration · functools · math module · random module · … (+4 more)
- Built-in functions — complete interview reference
collectionsmodule — deep diveheapq— min-heap on listsbisect— sorted list operationsitertools— combinatorial iterationfunctoolsmathmodulerandommodulere— regular expressionscopytyping(common hints)- Decision guide — which tool when?
Built-in functions — complete interview reference#
Core iteration and sequencing#
| Function | Returns | Notes |
|---|---|---|
len(x) |
int | O(1) for list/str/dict |
range(stop) / range(start, stop, step) |
range object | Lazy, immutable sequence |
enumerate(iterable, start=0) |
iterator of (i, val) |
Prefer over manual index |
zip(*iterables) |
iterator of tuples | Stops at shortest |
reversed(seq) |
reverse iterator | O(1) for list |
sorted(iterable, key=None, reverse=False) |
new list | Stable sort O(n log n) |
iter(obj) / next(it) |
iterator protocol | Manual iteration |
all(iterable) |
bool | Short-circuits on False |
any(iterable) |
bool | Short-circuits on True |
# sorted vs list.sort
a = [3, 1, 2]
b = sorted(a) # a unchanged, b sorted
a.sort() # a sorted in place, returns None
# key functions — critical pattern
sorted(intervals, key=lambda x: x[0])
sorted(words, key=str.lower)
sorted(students, key=lambda s: (-s.score, s.name)) # multi-key via tuple
Numeric and math helpers#
| Function | Purpose |
|---|---|
abs(x) |
Absolute value |
round(x, ndigits) |
Banker's rounding to nearest even |
divmod(a, b) |
(a // b, a % b) |
pow(base, exp) / pow(base, exp, mod) |
Power / modular exp |
min(*args, key=) / max(*args, key=) |
Extrema |
sum(iterable, start=0) |
Sum with optional start |
sum(range(10)) # 45
sum([[1], [2]], []) # [1, 2] — start matters for concat!
min([3, 1, 2], key=lambda x: -x) # 3
Type and introspection#
| Function | Purpose |
|---|---|
type(obj) |
Exact type |
isinstance(obj, cls) |
Subclass-aware check |
issubclass(cls, parent) |
Class hierarchy |
callable(obj) |
Has __call__? |
id(obj) |
Identity (CPython address) |
hash(obj) |
Hash value — KeyError if unhashable |
getattr(obj, name, default) |
Safe attribute access |
hasattr(obj, name) |
Attribute exists? |
vars(obj) |
__dict__ |
dir(obj) |
Names in scope |
isinstance(True, int) # True — bool subclasses int
isinstance([1], list) # True
isinstance([1], (list, tuple)) # tuple of types
Conversion and construction#
| Function | Purpose |
|---|---|
int(x, base=10) |
Parse integer |
float(x) |
Parse float |
str(x) |
String representation |
list(iterable) |
Materialize list |
tuple(iterable) |
Materialize tuple |
set(iterable) |
Unique elements |
dict(pairs) / dict(**kw) |
Build dict |
bool(x) |
Truthiness cast |
bytes(s, encoding) |
Encode to bytes |
chr(i) / ord(c) |
Code point ↔ char |
bin(n) / hex(n) / oct(n) |
String representations |
Functional tools#
| Function | Purpose | Lazy? |
|---|---|---|
map(fn, it, ...) |
Apply fn to items | Yes |
filter(fn, it) |
Keep truthy results | Yes |
zip |
Parallel iterate | Yes |
list(map(str, [1, 2, 3]))
list(filter(None, [0, 1, "", 2])) # [1, 2]
[x * 2 for x in range(5)] # preferred over map in modern Python
I/O and debugging#
print(*args, sep=" ", end="\n", file=sys.stdout)
input("prompt: ") # always returns str
help(func)
repr(obj) # unambiguous string form
ascii(obj) # ASCII-safe repr
breakpoint() # enter debugger (3.7+)
collections module — deep dive#
Counter — frequency maps#
from collections import Counter
c = Counter("aabbc")
c["a"] # 2
c["z"] # 0 — no KeyError
c.most_common(2) # [('a', 2), ('b', 2)]
# Update
c.update("aab") # add more counts
c.subtract("ab") # subtract (can go negative)
# Set-like math
c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)
c1 + c2 # Counter({'a': 4, 'b': 3})
c1 - c2 # Counter({'a': 2}) — drops non-positive
c1 & c2 # min counts
c1 | c2 # max counts
| Task | Approach |
|---|---|
| Anagram | Counter(a) == Counter(b) |
| Top k frequent | most_common(k) or heap |
| Multiset difference | Counter subtraction |
defaultdict — auto-vivify#
from collections import defaultdict
graph = defaultdict(list)
graph[1].append(2) # no KeyError
counts = defaultdict(int)
counts["x"] += 1
groups = defaultdict(set)
groups["tag"].add("item")
Factory must be callable returning new object: defaultdict(list), not defaultdict([]).
deque — double-ended queue#
from collections import deque
dq = deque([1, 2, 3], maxlen=5) # maxlen → auto-evict from opposite end
dq.append(4)
dq.appendleft(0)
dq.pop()
dq.popleft()
dq.rotate(1) # rotate right by 1
# BFS
queue = deque([start])
while queue:
node = queue.popleft()
for nei in graph[node]:
queue.append(nei)
| Operation | list |
deque |
|---|---|---|
| append/pop end | O(1)* | O(1) |
| pop(0) / insert(0) | O(n) | O(1) |
index access dq[i] |
O(1) | O(n) |
Use deque for BFS and sliding window queues — not random access.
OrderedDict#
Python 3.7+ regular dict preserves insertion order. OrderedDict adds:
move_to_end(key, last=True)popitem(last=False)— FIFO- Equality sensitive to order (unlike dict)
LRU cache pattern — see Introdicion to OOPs.
namedtuple#
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(1, 2)
p.x, p.y
p._asdict() # {'x': 1, 'y': 2}
p._replace(x=10) # new Point(10, 2)
# Python 3.7+ alternative
from dataclasses import dataclass
@dataclass
class Point2:
x: int
y: int
namedtuple is immutable; @dataclass can be mutable with less boilerplate.
ChainMap — layered dicts#
from collections import ChainMap
defaults = {"color": "red", "mode": "dark"}
user = {"color": "blue"}
settings = ChainMap(user, defaults)
settings["color"] # "blue" from user
settings["mode"] # "dark" from defaults
heapq — min-heap on lists#
import heapq
heap: list[int] = []
heapq.heappush(heap, 3)
heapq.heappush(heap, 1)
heapq.heappop(heap) # 1
nums = [3, 1, 4, 1, 5]
heapq.heapify(nums) # O(n) in-place
# Max-heap — negate values
max_heap = []
heapq.heappush(max_heap, -val)
-heapq.heappop(max_heap)
# Top-k without full sort
heapq.nlargest(3, nums) # O(n log k)
heapq.nsmallest(3, nums)
# Merge k sorted lists — push first of each, pop smallest, push next
| Need | Tool |
|---|---|
| Running median | Two heaps |
| Top k elements | nlargest or size-k min-heap |
| Dijkstra | (dist, node) min-heap |
Patterns: Heaps.
bisect — sorted list operations#
import bisect
nums = [1, 3, 3, 5, 7]
bisect.bisect_left(nums, 3) # 1 — first slot for 3
bisect.bisect_right(nums, 3) # 3 — after existing 3s
bisect.insort_left(nums, 3)
bisect.insort_right(nums, 6)
# Count elements < x
idx = bisect.bisect_left(nums, x)
# Insert in sorted order maintaining invariant
Use when maintaining a sorted dynamic array — not when you can use a dict/set instead.
itertools — combinatorial iteration#
from itertools import (
permutations,
combinations,
combinations_with_replacement,
product,
accumulate,
chain,
islice,
groupby,
pairwise, # 3.10+
count,
cycle,
repeat,
)
list(permutations([1, 2, 3], 2))
list(combinations([1, 2, 3], 2))
list(product([0, 1], repeat=3))
list(accumulate([1, 2, 3, 4])) # prefix sums
list(accumulate([1, 2, 3, 4], max)) # prefix max
# chain — flatten
list(chain.from_iterable([[1, 2], [3]]))
# groupby — consecutive groups only (sort first!)
data = [("a", 1), ("a", 2), ("b", 3)]
for key, group in groupby(data, key=lambda x: x[0]):
print(key, list(group))
| Problem | itertools analog |
|---|---|
| All subsets | combinations or bitmask |
| Permutations | permutations |
| Cartesian product | product |
| Prefix sums | accumulate |
Backtracking: Backtracking.
functools#
from functools import cache, lru_cache, cmp_to_key, reduce, partial
@cache
def fib(n: int) -> int:
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
@lru_cache(maxsize=128)
def dp(i: int, j: int) -> int:
...
# reduce — fold iterable (use sparingly; prefer loop or sum)
from functools import reduce
reduce(lambda acc, x: acc + x, [1, 2, 3], 0)
# partial — fix arguments
from functools import partial
double = partial(pow, 2) # careful with arg order
| Decorator | Cache | Hashable args required |
|---|---|---|
@cache |
Unlimited | Yes |
@lru_cache(maxsize=n) |
Bounded LRU | Yes |
Pass tuples not lists to memoized functions: dp(i, tuple(nums)).
math module#
import math
math.inf, -math.inf
math.nan
math.isinf(x), math.isnan(x), math.isclose(a, b)
math.gcd(12, 18) # 6
math.lcm(4, 6) # 12 (3.9+)
math.ceil(3.2), math.floor(3.8)
math.trunc(-3.7) # -3
math.sqrt(2), math.log(n, 2)
math.isqrt(10) # 3 — integer sqrt (3.8+)
math.comb(5, 2) # 10 — binomial (3.8+)
math.perm(5, 2) # 20
Use math.isclose for float comparisons — see Operators.
random module#
import random
random.seed(42) # reproducibility
random.random() # [0.0, 1.0)
random.randint(1, 6) # inclusive both ends
random.choice([1, 2, 3])
random.choices(pop, k=10) # with replacement
random.sample(pop, k=3) # without replacement
random.shuffle(lst) # in-place
random.uniform(a, b)
Rare in deterministic interview problems unless randomized algorithms are specified.
re — regular expressions#
import re
re.match(r"^\d+", "42abc") # at start only
re.search(r"\d+", "abc42") # first anywhere
re.fullmatch(r"\d+", "42") # entire string
re.findall(r"\d+", "a1b22")
re.finditer(r"\d+", "a1b22") # iterator of match objects
re.sub(r"\s+", " ", text)
re.split(r",\s*", "a, b, c")
pattern = re.compile(r"(?P<name>\w+)")
m = pattern.search("hello")
m.group("name")
Flags: re.IGNORECASE, re.MULTILINE, re.DOTALL.
copy#
import copy
original = [[1, 2], [3, 4]]
shallow = copy.copy(original) # or original.copy() for list
deep = copy.deepcopy(original)
shallow[0].append(99) # affects original[0]
deep[0].append(99) # does not affect original
typing (common hints)#
# Python 3.9+ — prefer built-in generics
def find(nums: list[int], target: int) -> int | None: ...
# Older style
from typing import Optional, List, Dict, Tuple, Union, Callable
def apply(fn: Callable[[int], int], x: int) -> int: ...
Runtime: hints are stored in __annotations__ — not enforced without mypy/pyright.
Decision guide — which tool when?#
| Problem signal | Reach for |
|---|---|
| Count frequencies | Counter |
| Graph adjacency | defaultdict(list) |
| BFS / monotonic queue | deque |
| Top-k streaming | heapq size-k heap |
| Sorted dynamic array | bisect |
| All combos/perms | itertools or backtracking |
| Memoized recursion | @cache |
| Missing dict key default | .get() or defaultdict |
| Merge k sorted | heapq push/pop |
| Prefix sums | accumulate or manual loop |
| Parse digits/words | str methods first, then re |
Interview traps (quick reference)#
| Trap | What goes wrong | Safe approach |
|---|---|---|
list as heap |
O(n) extract-min | heapq |
sorted vs .sort() |
.sort() returns None |
Don't assign sort result |
groupby without sort |
Only groups consecutive | Sort first |
@lru_cache + list arg |
Unhashable | Use tuple |
Counter subtraction |
Negative counts dropped | Check semantics |
deque[i] random access |
O(n) | Use list for indexing |
sum with wrong start |
Unexpected concat | Default start=0 |
| Over-importing | Noise | Import at top, only what's needed |
Mental model checklist#
- When do you use
Countervs manual dict counting? - Why is
dequepreferred overlistfor BFS queues? - What is the max-heap trick with
heapq? - What does
@cacherequire about arguments? - When is
bisectbetter than a hash map?
What's next#
| Topic | Page |
|---|---|
| Core collections | Data Structures |
| Environment setup | The Python Environment |
| Intermediate stdlib | Data Handling and Standard Library |
| DSA patterns | Programming |