Python API reference
Every call worth knowing on the collections, heapq, bisect, itertools and the built-in types, then on threads, queues, executors, processes, asyncio, files and os: what it does, what it costs, and what it prints.
Do I need to memorise all of this?
No. Know that each tool exists and what it is for, and know five or six calls cold: Counter and most_common, defaultdict(list), deque with popleft, heappush and heappop, bisect_left, and sorted with a key. The rest you can recognise when you see it, and an interviewer will usually let you look up an argument order.
Which Python version do these examples run on?
The build that recorded every output on this page runs a current CPython 3. Everything here has been in the standard library since Python 3.10, which added Counter.total, pairwise and the key argument to bisect, except one row: concurrent.futures.TimeoutError became the built-in TimeoutError in 3.11. Interview environments are usually at least that new, but say which version you are assuming if you use one of those.
Why does heapq have no max-heap?
It was written as a min-heap only, and for a long time the standard answer was to push the negative of each number and negate again on the way out, or to push a tuple whose first part is the negated priority. Recent Python versions add max-heap functions, but most interview environments run an older Python, so the negation is still the safe habit.
What does "O(1) average" mean for a dictionary or a set?
A lookup hashes the key and looks in one slot, which takes the same time however many keys there are. Two keys can land in the same slot, and then a short search follows, so the cost is constant on average rather than in every single case. For interview purposes you say O(1) and move on.
Are these costs guaranteed by the language?
They are how CPython implements them rather than promises in the language reference, but they have been stable for many years and they are what an interviewer means. The ones worth being able to justify are the surprises: list.pop(0) and insert at the front are O(n), a slice copies, x in a list is O(n), and string += in a loop is quadratic.
Why does every wait in the threading and asyncio tables carry a timeout?
Because a wait with no timeout is how concurrent code hangs, and a hang gives you nothing to debug in a round. Each blocking call in those tables shows the bounded form: join(timeout), get(timeout), result(timeout), wait_for. Know what each one does when the time runs out: join returns None and you check is_alive, Queue.get raises queue.Empty, Future.result raises TimeoutError, and Event.wait returns False.
Is flush enough to make a write safe?
It is enough to survive your process crashing, and not enough to survive the machine going down. write puts the bytes in Python’s buffer, flush hands them to the kernel, and os.fsync(f.fileno()) asks for them on the disk. The files and os tables record the file size at each step, and the systems I/O page explains what each layer survives.