Loading...
Loading...
Python interview guide
Questions from the interview-preparation section: core Python, OOP, collections and output prediction. Every answer is short enough to say aloud, and every question links to the lesson that teaches it.
60 questionsLast updated
A Lock allows one thread at a time into a section of code. A deadlock happens when threads wait for each other's locks in a cycle and none can continue. Avoid it by taking locks in a fixed order and using with so locks are always released.
It has locking built in, so several threads can put and get without extra locks. get waits when empty, which gives a simple producer-consumer pattern. The queue module is the safest way to hand work between threads.
Concurrency is managing many tasks that overlap in time, even on one core. Parallelism is running tasks at exactly the same time on several cores. asyncio and threads give concurrency, and with the GIL only processes give true parallel Python code.
Lesson: Threads, Processes, asyncio and the GILIt is an optional build of CPython, first offered in version 3.13, that runs without the GIL, so threads can use several cores for Python code. It is not the default, some extension modules may not support it yet, and single-thread speed can differ. The standard build still has the GIL.
Lesson: Threads, Processes, asyncio and the GILCPython uses reference counting to free most objects as soon as nothing refers to them, plus a generational cyclic garbage collector for reference cycles. Objects live on a private heap managed by Python, with small-object allocators for speed. The programmer does not free memory by hand.
Follow-up: Is this true for every Python implementation? No. PyPy and others use different garbage collectors, so objects may be freed later than in CPython.
Common mistake: Saying Python has no memory management. It has automatic management, and you can still leak memory.
Lesson: Memory, Reference Counting and Garbage CollectionThere are three: generation 0 for new objects, then 1 and 2 for survivors. Each has a threshold, and a collection of a younger generation runs often and is cheap. The idea is that most objects die young, so checking only young ones saves time.
Lesson: Memory, Reference Counting and Garbage CollectionA shallow copy makes a new outer container but shares the inner objects, so a change inside is visible in both. A deep copy copies all levels, so the two are independent. Use copy.copy and copy.deepcopy, or the copy() methods for shallow copies.
Follow-up: When is a shallow copy enough? When the contents are immutable, like numbers and strings, or you will replace items and not change them in place.
Lesson: Memory, Reference Counting and Garbage Collection__del__ is a finalizer called just before an object is freed. When it runs is not guaranteed outside CPython's immediate counting, and it may never run at exit. For cleanup, prefer context managers with with or weakref.finalize.
__slots__ lists the allowed attribute names, so instances have no __dict__ and use less memory. It helps when you create millions of small objects. The costs are that you cannot add other attributes, and inheritance needs care.
Immutable objects, such as int, str and tuple, cannot change, so every change makes a new object, and sharing them is safe. Mutable objects, such as lists and dicts, change in place, so aliases see the change. This is the source of many aliasing bugs.
A generator keeps one position and moves only forward, so once it is exhausted it gives nothing. Create a new generator for each pass, or store the items in a list if you need to read them several times. The list costs memory, so choose by the size of the data.
Follow-up: Does reading an exhausted generator raise an error? No. A loop over it just does nothing, which makes the bug silent.
Lesson: Advanced Python Drill and CheckpointUse @contextmanager for simple setup and cleanup because it is short. Use a class when you need extra methods, state kept between uses, or exact control over exceptions in __exit__. Both work with with in the same way.
counter += 1 safe?No. The statement is several steps, read, add and write, and a thread switch can happen between them. Two threads can read the same value and lose an update. Use a Lock, an atomic structure or a queue.
CPython counts references to each object and frees it when the count reaches zero, which is quick and predictable. Its limit is cycles, whose counts never reach zero. A cyclic garbage collector handles those.
Lesson: Advanced Python Drill and CheckpointUse tracemalloc to take snapshots and compare them, or check object counts with gc.get_objects(). Look for growing caches, global lists and objects kept alive by references. Fix the owner of the reference, not the symptom.
It lets you refer to an object without keeping it alive, which avoids leaks in caches and registries. When the object is freed, the weak reference returns None, or the entry disappears from a WeakValueDictionary. The object must support weak references, so plain int and str do not.
0.1 + 0.2 == 0.3 false?Floats are stored in binary and 0.1 has no exact binary form. The sum is slightly above 0.3. Compare with round(), math.isclose, or store money in whole cents.
Follow-up: Does the same happen with integers? No. Python ints are exact and have no size limit, so 2 ** 100 never overflows.
Common mistake: Blaming Python. Every language that uses IEEE 754 floats behaves this way.
Lesson: Output Puzzles: Operators, Division and Truthinesss[::-1] do?It takes the whole string with a step of -1, so it walks backward and returns a reversed copy. It works for lists and tuples too.
Follow-up: What does s[5:2] return? An empty string, because with a positive step the start is already past the stop. Slices do not raise errors for that.
Common mistake: Thinking the stop index is included.
Lesson: Output Puzzles: Strings, Slicing and Immutabilitylen(text) the number of bytes?No. It counts characters (code points). The byte count depends on the encoding, so use len(text.encode()) for UTF-8 bytes.
Follow-up: Can two strings look the same but be unequal? Yes. A letter with an accent can be one code point or a letter plus a combining mark. unicodedata.normalize makes them comparable.
Common mistake: Assuming one visible character is always one code point.
Lesson: Output Puzzles: Strings, Slicing and ImmutabilityA shallow copy makes a new outer container but reuses the inner objects. A deep copy, from copy.deepcopy, copies the inner objects too, so changes do not leak.
Follow-up: Is list(a) shallow or deep? Shallow. For a list of numbers that is enough, but for a list of lists it still shares the inner lists.
Common mistake: Using [:] on a list of lists and expecting full independence.
count += 1 inside a function raise UnboundLocalError?An assignment anywhere in a function makes the name local to that function. count += 1 reads the local before it has a value. Use global count, or better, pass the value in and return the new one.
Follow-up: When is nonlocal used? In a nested function to rebind a variable of the enclosing function, as in a counter.
Common mistake: Thinking Python reads the global first and only then creates a local.
Lesson: Output Puzzles: Scope, Closures in Loops and Class vs Instance AttributesFrom the bottom. The last line gives the exception type and message. The lines above show the calls in order, with the failing line last. I find my own file in the list and look at that line first.
Follow-up: What if the failing line is inside a library? I walk up to the last frame in my own code. That line passed the bad value into the library.
Common mistake: Reading only the top of the traceback and missing the real message.
Lesson: Reading Tracebacks and Finding BugsNone instead of a number. What do you check first?That it has a return on every path. A function that falls off the end returns None. Methods like list.sort() also return None.
Follow-up: How do you see which branch returned None? Trace a small input, and add a test for each branch, including the empty input.
Common mistake: Checking the calling code first instead of the function.
Lesson: Reading Tracebacks and Finding BugsI look for a line that cannot run: a wrong operand type, a missing key or index, a name used before it has a value. If one exists, the output stops there, and I name the exception.
Follow-up: Does earlier output still print before the error? Yes. Lines before the failing one run and print normally.
Common mistake: Writing the output of the lines after the error.
Lesson: Output Prediction Timed Drill CheckpointIt shows I understand the problem and gives a correct baseline. The repeated work inside it usually points straight to the better idea.
Lesson: Explaining Your Approach and Its Cost Out LoudIt is O(1) on average because of hashing. In a very unlucky case many keys collide and it slows down, so I say 'on average'.
Lesson: Explaining Your Approach and Its Cost Out LoudYes. a[i:j] creates a new list and copies its items, so it costs O(j - i) time and space. In a loop or a recursion, slices can quietly turn O(n) into O(n squared).
Each pending call keeps a frame, so the space is the maximum depth. A tree of height h uses O(h) stack, and a recursive sum over n items uses O(n).
Lesson: Explaining Your Approach and Its Cost Out LoudI ask which limit matters. With a large input and tight memory I may sort in place; otherwise a set or dict is usually simpler and faster.
Lesson: Explaining Your Approach and Its Cost Out LoudI state the idea that makes it right, such as 'each step discards a value that cannot be part of the answer'. Then I test one normal case and two edge cases.
Lesson: Explaining Your Approach and Its Cost Out LoudWhen the data is sorted or has a structure that tells me which pointer to move, like a pair sum on a sorted list. Each step discards at least one value, so the pass is O(n).
Lesson: Common Pattern and Data Structure QuestionsThey answer many range-sum questions in O(1) after one O(n) pass. With a dict they also count subarrays with a given sum.
Lesson: Common Pattern and Data Structure QuestionsA stack whose items stay in increasing or decreasing order, where each new item pops everything it beats. It answers 'next greater item' questions in O(n) because each item is pushed and popped once.
Lesson: Common Pattern and Data Structure QuestionsWhen I remove from the front, such as in a queue or breadth-first search, or need a window maximum. popleft is O(1) while list.pop(0) is O(n).
Yes, it is standard Python and interviewers accept it. I also say what it does underneath, a dict of counts built in O(n), in case they ask me to write it by hand.
Lesson: Common Pattern and Data Structure QuestionsI say both, compare their time and space for this input size, and pick the simpler one that meets the limits. Explaining the trade-off scores more than the choice itself.
Lesson: Common Pattern and Data Structure QuestionsInorder: left, node, right. Because every left value is smaller and every right value is larger, the output is sorted.
Lesson: Tree, Graph and Dynamic Programming QuestionsI use a deque and process len(queue) nodes per round to separate levels. The cost is O(n) time and up to O(n) space for the widest level.
A graph can contain cycles, so without a seen set the search loops forever or repeats work. With it each node is handled once, giving O(V + E).
Lesson: Tree, Graph and Dynamic Programming QuestionsI run a topological sort with in-degrees: if fewer nodes than V get processed, a cycle exists. Alternatively DFS with three states (new, in progress, done) detects a back edge.
Lesson: Tree, Graph and Dynamic Programming QuestionsI look for a best value or a count, choices at every step, and the same smaller subproblems repeating. Writing the plain recursion and seeing repeated calls confirms it.
Lesson: Tree, Graph and Dynamic Programming QuestionsI say which part of my solution holds everything in memory, then change it to read in pieces or as a stream. If the problem needs sorting, I sort chunks and merge them.
Lesson: Following Up on Your Solution: Huge Inputs and StreamsCount, sum, minimum, maximum, and from them the mean. Things like the median, distinct count or most frequent value need more memory.
Lesson: Following Up on Your Solution: Huge Inputs and StreamsI cannot sort or revisit, so I keep a small running state, like counts, a heap or a window. I also say what answer I can give exactly and what only approximately.
Lesson: Following Up on Your Solution: Huge Inputs and StreamsI check what my solution assumed. A set loses counts, so I use a Counter. Two pointers need to skip equal values to avoid repeated results.
Lesson: Following Up on Your Solution: Huge Inputs and StreamsA heap holds the current front item of each of the k sorted inputs. I pop the smallest, push the next item from the same input, and repeat: O(n log k) for n items.
Lesson: Following Up on Your Solution: Huge Inputs and StreamsStatic preprocessing like prefix sums then needs rebuilding, O(n) per update. I would mention a structure built for updates, such as a Fenwick tree or a segment tree, with O(log n) per update and query.
Lesson: Following Up on Your Solution: Huge Inputs and StreamsAbout 5 minutes to clarify and plan, 20 to code, 10 to test and discuss cost, and the rest for follow-ups. If I am slow I code the brute force first so there is a working answer.
Lesson: DSA in Python Interviews CheckpointEmpty input, one item, duplicates, negative numbers, the largest allowed size, and an input with no answer. I name them before coding so the code handles them.
Lesson: DSA in Python Interviews CheckpointI count the number of calls and the work per call for time, and the maximum depth for space. With memoization the calls drop to the number of distinct states.
Lesson: DSA in Python Interviews CheckpointI say what each choice costs and gains, like a dict that makes lookups O(1) but uses O(n) space. Then I say why my pick fits the stated limits.
Lesson: DSA in Python Interviews CheckpointQuality matters more than count. A set of 100 to 150 problems covering every pattern, each revised until you can explain it without notes, is a sound target.
Lesson: DSA in Python Interviews CheckpointI summarise: what the code does, its time and space, and which edge cases I tested. Then I invite follow-ups.
Lesson: DSA in Python Interviews Checkpointis do and how is it different from ==?== compares values and is compares identity, the same object in memory. I use is for None only.
Common mistake: Using is to compare strings or numbers. It may work by accident for small values and then fail.
Brute force: start at each position and extend until a repeat, O(n squared). Better: a window with a dictionary of last positions; when a code repeats inside the window, move the start just past the old copy. One pass, O(n).
Follow-up: Can it be faster than O(n)? No: every item must be read at least once, so O(n) is the best possible.
Common mistake: Jumping to the final code with no idea first. The interviewer wants to hear the path.
Lesson: Mock interview 2: a medium problem and OOP@property instead of a plain attribute?A property keeps obj.attr syntax but can check a value on set or compute a value on get. I can add the rule later without changing callers.
Follow-up: What is __repr__ for? It returns a text meant for developers, shown in logs and the shell, ideally enough to rebuild the object.
Common mistake: Writing get_x and set_x methods in Python by default.
Sixty seconds: it lets clients list products, place orders and check stock. I own the order rules; stock cannot go below zero, and errors return a clear message and status. I used a dataclass for products and tests for each rule. Next I would add paging to the product list.
Follow-up: What was the hardest bug? Two orders for the last item both passed the check. I fixed it by doing the check and the update in one transaction.
Common mistake: Listing technologies only. Say what problem it solves and what you decided.
Lesson: Mock interview 3: project and SQL roundAn index is a sorted lookup structure on a column, so the database finds rows without reading the whole table. It helps with WHERE, JOIN and ORDER BY on that column, but costs space and slows writes.
Common mistake: Saying "indexes always make queries faster". They have a write cost.
Lesson: Mock interview 3: project and SQL roundI took three timed mocks, scored them, and sorted topics by score. I spent most time on the lowest ones, practised answers aloud, and kept a log of missed questions.
Follow-up: What improved most? My speed in explaining: I now answer in a definition, an example and a trap.
Common mistake: Saying "I read many notes". Show a plan and a result.
Lesson: Final revision plan for Python interviewsI know the basics well, solve problems with the standard library, write small classes with clear rules, query data with SQL and explain my choices. My projects show the same habits.
Common mistake: A list of adjectives. Give evidence from projects.
Lesson: Final revision plan for Python interviewsEach lesson has quizzes, practice and more interview questions on the same topic.
Open the first lesson