Skip to main content

Python Interview Questions for 2026: 50+ Questions Across Data Structures, OOP, Async, and the Tricky Concepts Interviewers Love

Python interview questions in 2026 test more than syntax. Interviewers probe decorators, generators, the GIL, async patterns, and the standard-library quirks that separate the candidate who scripted in Python from the engineer who understands it. This guide covers 50+ questions across data structures, OOP, async, and tricky concepts, plus the new-grad-specific prep plan.

By Alex Chen, Founder, InterviewChamp.AI · Last updated

23 min read

What Python interview questions actually test in 2026

Python interview questions in 2026 test three things in this order: whether you can write idiomatic Python (not just correct code), whether you understand the language's quirks at a level deeper than syntax, and whether you can talk through your reasoning under live observation. The syntax check is the floor. Almost every CS new grad clears it. The idiom check and the deep-language check are where most interviews are won or lost.

The 2026 hiring environment has shifted the bar. As of the 2025-2026 hiring cycle, Python is the dominant language for backend, data engineering, machine learning, DevOps, and analytics roles. That means more interviewers are reading Python code and more of them know what idiomatic Python looks like. The candidate who initializes an empty list and appends in a loop when a comprehension would do is no longer "fine, just verbose." They read as someone who used Python without learning Python. The bar is fluency, not literacy.

The distribution of question types most new-grad candidates report seeing in their loops:

  • 30-40% data structures (lists, tuples, sets, dicts, time complexity)
  • 20% object-oriented programming (classes, inheritance, dunder methods)
  • 20% algorithm patterns implemented in Python
  • 15% language-specific concepts (decorators, generators, GIL, async)
  • 5-10% standard-library fluency (collections, itertools, functools)

The language-specific 15% slice is the one most candidates underprepare for. It is also the slice that disproportionately determines the outcome.

How Python interview questions differ from general coding interviews

A general coding interview in any language tests algorithm fluency, problem decomposition, and communication. A Python interview adds a fourth dimension: language-specific idiom and concept fluency. Three concepts in particular show up over and over in 2026 Python interviews and rarely appear in interviews for other languages:

Decorators. A first-class concept in Python in a way they aren't in Java or C++. Almost every Python codebase uses decorators (@property, @staticmethod, @classmethod, @functools.lru_cache, framework-specific decorators in Flask or FastAPI), and interviewers expect candidates to understand how they work, not just how to apply them.

Generators and the yield keyword. Lazy evaluation is foundational to idiomatic Python, especially for any role that touches large datasets. A candidate who uses range(1_000_000) and assumes it materializes a list (it doesn't, range in Python 3 is lazy) is not the candidate the team wants debugging a streaming pipeline.

The GIL. A polarizing topic that nonetheless gets asked at almost every Python interview above the most-junior tier. "What is the GIL and how does it affect threading?" is one of the most-Googled Python interview questions for a reason. Interviewers ask it as a litmus test for whether the candidate understands why their threaded code didn't speed up.

Three more concepts that round out the language-specific surface area: context managers (with blocks), dunder methods (the special methods that make your class behave like a built-in), and the standard library (especially collections, itertools, and functools). A candidate who reaches for collections.Counter instead of building a counter dict manually is showing fluency in two seconds that takes other candidates two minutes to demonstrate.

Honest call here: if you only have a weekend before the Python round, drill decorators and collections.Counter first. They show up so often that being fast on those two will compensate for being slow on three others.

A typical path for the new grad we built this guide for: 487 applications since May 2025, 14 phone screens, zero offers, 11 months in, 600 LeetCode problems solved. Strong on patterns, weak on Python idioms because most of the LeetCode grind was in Java. One stuck OA from a Series B fintech on Monday morning, in Python this time, on HackerRank. Bombed the Meta phone screen 8 minutes in when the interviewer asked about the GIL. The engineer was nice tho. The candidate doesn't need more LeetCode. They need decorators, collections.Counter, and the GIL story drilled tight enough to recite half-asleep at 9am on Monday.

The 50+ Python interview questions you should rehearse

What follows is a structured rehearsal set covering the seven categories that show up most. Each question has a sample answer outline. Not a full canned response, but the bones of what a strong answer covers. Adapt the language to your own voice. The structure is the load-bearing part.

Python data structures interview questions (10 Q)

Q1. What's the difference between a list and a tuple?

Lists are mutable, tuples are immutable. Tuples are hashable (so they can be dict keys or set members) and slightly faster to allocate. Use tuples for records ("this is a fixed shape"), lists for sequences ("this can grow or shrink").

Q2. How does a dict work under the hood?

A dict is a hash table. Keys are hashed (hash(key)) and the hash determines the bucket. Collisions are resolved by open addressing. Lookup, insert, and delete are O(1) average, O(n) worst case. Since Python 3.7, dicts are insertion-ordered as a language guarantee.

Q3. What is the time complexity of common list operations?

Index access and append: O(1). Pop from the end: O(1). Pop from the front or insert at index 0: O(n) because every element shifts. Membership test (x in lst): O(n). For O(1) front-pop, use collections.deque.

Q4. What is the time complexity of common dict and set operations?

Insert, lookup, delete, membership test: O(1) average for both. Iteration: O(n). Sets are essentially dicts without values.

Q5. What is a hashable object in Python?

An object is hashable if it has a __hash__ method that returns a consistent integer and an __eq__ that respects the hash contract (equal objects must have equal hashes). All immutable built-ins are hashable: ints, floats, strings, tuples of hashables. Lists, dicts, and sets are not hashable. Custom classes are hashable by default (by object identity) unless you override __eq__ without also overriding __hash__.

Q6. How do you reverse a list in Python?

Three idiomatic options: lst.reverse() reverses in place; lst[::-1] returns a new reversed list; reversed(lst) returns a lazy iterator. Pick by use case: .reverse() for in-place, slice for a new list, reversed() if you just need to iterate.

Q7. What's the difference between is and ==?

== calls __eq__ and tests value equality. is tests identity, whether two names point at the same object in memory. a == b can be true while a is b is false. The classic gotcha: None, True, False, and small integers (-5 to 256) are cached, so is works on them by accident. For any other value you should always use ==.

Q8. How do you merge two dicts in Python?

In Python 3.9+, use the | operator: merged = a | b. In earlier versions, use {**a, **b}. For in-place merge, use a.update(b). If keys collide, the right-hand operand wins.

Q9. What does dict.get(key, default) do that dict[key] doesn't?

dict[key] raises KeyError if the key is missing. dict.get(key, default) returns the default (or None if no default is provided). The interview-relevant follow-up: when should you use defaultdict instead? Answer: when you're going to mutate the default (append to a list, increment a counter). get returns a new default each call, but defaultdict creates and stores the default in the dict on first access.

Q10. How do you remove duplicates from a list while preserving order?

seen = set()
unique = [x for x in lst if not (x in seen or seen.add(x))]

Or in Python 3.7+: list(dict.fromkeys(lst)). Both are O(n) and preserve insertion order.

Python OOP interview questions (8 Q)

Q11. How does inheritance work in Python?

A class inherits from one or more parent classes by listing them in parentheses: class Dog(Animal):. The subclass gets all the methods and attributes of the parent. Override by redefining; call the parent version with super().method(). Python supports multiple inheritance. The resolution order is the MRO (Method Resolution Order), computed by the C3 linearization algorithm.

Q12. What is the MRO?

The Method Resolution Order is the sequence Python follows when looking up a method on a class with multiple parents. It's computed by C3 linearization, which guarantees a consistent ordering that respects each parent's MRO. Inspect it with ClassName.__mro__ or ClassName.mro(). The interview-relevant case is the diamond problem: when class D inherits from B and C, both of which inherit from A, the MRO is D → B → C → A, and super() follows that order.

Q13. What's the difference between classmethod, staticmethod, and an instance method?

An instance method receives self as the first argument and operates on an instance. A classmethod receives cls and operates on the class itself, useful for alternative constructors (from_string, from_dict). A staticmethod receives nothing extra. It's a regular function namespaced under the class, used when the logic belongs conceptually to the class but doesn't need access to the instance or the class.

Q14. What is the @property decorator?

@property turns a method into a read-only attribute. Instead of obj.price() you write obj.price, but the method body still runs every access. Add a setter with @price.setter to make it writable. The use case: encapsulate computed attributes (e.g., area from width * height) without breaking the attribute-access API.

Q15. What's the difference between __init__ and __new__?

__new__ allocates and returns the new instance. __init__ initializes the already-allocated instance. For ordinary classes you only override __init__. Override __new__ when subclassing an immutable type (int, str, tuple), implementing a singleton, or building a metaclass. __new__ is a static method that receives cls. __init__ is an instance method that receives self.

Q16. What are dunder methods? Name five.

Dunder methods are Python's special methods, invoked implicitly for built-in operations. Five common ones: __init__ (initialization), __repr__ (developer-readable representation), __str__ (user-readable string), __len__ (enables len(obj)), __eq__ (enables ==). Others worth knowing: __hash__, __iter__, __next__, __getitem__, __setitem__, __enter__, __exit__, __call__.

Q17. How do you make a class iterable?

Define __iter__ to return an iterator (an object with __next__), or define __iter__ as a generator using yield. The iterator's __next__ returns the next value or raises StopIteration to signal the end. For most classes the generator approach is cleaner because Python handles the iterator state for you.

Q18. What is duck typing?

The principle that an object's suitability for an operation depends on whether it has the required methods, not on its type. A function that calls obj.read() works on any object with a read method, regardless of inheritance. Python prefers duck typing over explicit type-checking. With 2026's type hints (PEP 544 Protocols), you can statically type-check duck types without giving up the runtime flexibility.

Python decorators interview questions (5 Q)

Q19. What is a decorator?

A callable that takes a function and returns a function. The @decorator syntax above a function definition is sugar for f = decorator(f). Common decorators: @property, @staticmethod, @classmethod, @functools.lru_cache, framework-specific decorators in Flask, FastAPI, and Django.

Q20. Write a decorator that logs the execution time of a function.

import functools, time

def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"{func.__name__} took {time.perf_counter() - start:.4f}s")
        return result
    return wrapper

The @functools.wraps line is the load-bearing detail. It preserves the wrapped function's __name__, __doc__, and other metadata. Without it, wrapper.__name__ is "wrapper", which breaks introspection and debugging.

Q21. What does functools.wraps do?

It copies the wrapped function's metadata (__name__, __doc__, __module__, __qualname__, __annotations__) onto the wrapper. Without it, a decorated function appears to be the wrapper for introspection purposes, breaking help(), IDE tooling, and any code that reads __name__. Always use it.

Q22. How do you write a decorator that takes arguments?

Three levels of nesting: the outer function takes the decorator arguments, the middle function takes the decorated function, and the inner function is the actual wrapper.

def repeat(n):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(n):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def greet():
    print("hi")

The pattern is the most common decorator-interview follow-up. Memorize the three-level structure.

Q23. What's the difference between a function decorator and a class decorator?

Both follow the same pattern (take a callable, return a callable), but a class decorator wraps a class instead of a function. Useful for adding methods, modifying attributes, or registering the class in a registry. The wrapped callable can also be a class implementing __call__ instead of a nested function. That's often cleaner when the decorator needs to maintain state.

Python generators + iterators interview questions (5 Q)

Q24. What's the difference between yield and return?

return exits a function and returns a value. yield pauses a function, returns a value, and remembers where it stopped. The next call resumes from there. A function with at least one yield is a generator function. Calling it returns a generator object that doesn't run the body until you iterate it.

Q25. What's the memory difference between a list comprehension and a generator expression?

A list comprehension [x*2 for x in range(10**6)] builds the entire list in memory, about 8 MB for a million ints. A generator expression (x*2 for x in range(10**6)) builds a lazy iterator with constant memory, computing each value on demand. For large datasets or infinite sequences, generators are the difference between a clean iteration and an out-of-memory crash.

Q26. How do you write a generator that yields the Fibonacci sequence?

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

Infinite generator, constant memory. Consume with itertools.islice(fib(), 10) to take the first 10 values without exhausting the (infinite) iterator.

Q27. What is the difference between an iterator and an iterable?

An iterable is anything you can loop over. It has an __iter__ method that returns an iterator. An iterator has both __iter__ (returning itself) and __next__ (returning the next value or raising StopIteration). Lists, tuples, dicts, sets, and strings are iterables but not iterators. Generators are both.

Q28. What does itertools give you that built-in iteration doesn't?

A library of lazy iterator-building blocks: chain to concatenate iterables, islice to take a slice without materializing, groupby to group consecutive equal values, product for Cartesian products, combinations and permutations for combinatorics, accumulate for running totals. The interview signal is whether you reach for itertools when the standard solution would build an intermediate list.

Python async / concurrency interview questions (6 Q)

Q29. What is the GIL and why does it exist?

The Global Interpreter Lock is a mutex inside CPython that allows only one thread to execute Python bytecode at a time. It exists because CPython's memory management uses non-thread-safe reference counting. The GIL is the simplest way to keep the counts consistent. The cost is that CPU-bound multithreaded code doesn't speed up. The benefit is that single-threaded code is fast and C extensions don't need to worry about thread safety. PEP 703 introduced an optional free-threaded build in 3.13, but the GIL is still the default in 2026.

Q30. When should you use threading vs multiprocessing vs asyncio?

  • threading: I/O-bound work, low-to-moderate concurrency (a few dozen threads). The GIL releases on I/O, so threads do help here.
  • multiprocessing: CPU-bound work. Separate processes, separate interpreters, separate GILs. True parallelism.
  • asyncio: I/O-bound work, high concurrency (thousands of connections). Single-threaded cooperative scheduling avoids thread-context-switch overhead.

Q31. What is a coroutine?

A coroutine is a function declared with async def. Calling it returns a coroutine object that doesn't run until awaited. Inside a coroutine, await suspends execution until an awaitable (another coroutine, a future, a task) completes. Coroutines are the building block of asyncio.

Q32. How does asyncio.gather work?

asyncio.gather(coro1, coro2, ...) runs multiple coroutines concurrently and returns a list of their results. It's the canonical way to fan out parallel I/O work. If any coroutine raises, the others continue but the exception is re-raised by gather. For more control, use asyncio.TaskGroup (Python 3.11+).

Q33. What's a common mistake with asyncio?

Calling a regular blocking function inside an async def. The blocking call freezes the entire event loop until it returns, defeating the purpose of async. The fix is asyncio.to_thread(blocking_func, args) (Python 3.9+), which runs the blocking function in a thread pool while the event loop continues. The deeper mistake is mixing time.sleep (blocking) with asyncio.sleep (awaitable) in the same code path.

Q34. How would you parallelize a CPU-bound task in Python?

Use multiprocessing.Pool or concurrent.futures.ProcessPoolExecutor. Each process gets its own interpreter and bypasses the GIL. The cost is inter-process communication overhead. Data has to be pickled and shipped. For sub-millisecond tasks the overhead exceeds the speedup. For tasks taking 100ms+ the parallelism wins. For NumPy-heavy workloads, the underlying C code already releases the GIL, so threading can also work.

Python standard-library tricky questions (5 Q)

Q35. What does collections.Counter do?

It's a dict subclass for counting hashable elements. Counter(['a', 'b', 'a']) returns Counter({'a': 2, 'b': 1}). Useful methods: .most_common(n) returns the n highest-count items as a list of tuples, + adds two counters, - subtracts, & takes the minimum per key (intersection), | takes the maximum (union). The signal: if you see "count the frequency of X" in a problem, reach for Counter.

Q36. What's the difference between dict and collections.defaultdict?

defaultdict(factory) automatically creates a default value (via the factory function) when a missing key is accessed. d = defaultdict(list); d['key'].append(1) works without first initializing d['key'] = []. The factory can be list, int, set, or any zero-arg callable. The trap: accessing a missing key creates and stores the default, which can mask bugs in code that didn't intend to insert.

Q37. What is functools.lru_cache?

A decorator that memoizes a function. Caches the return value for each input combination so repeated calls return the cached value instead of recomputing. @lru_cache(maxsize=128) keeps the 128 most-recent results. maxsize=None means unlimited. Wrap any pure function with expensive computation (e.g., recursive Fibonacci) to get an exponential speedup for free. The 2026 update: @functools.cache (Python 3.9+) is the same with unlimited size.

Q38. What's the difference between collections.deque and a list?

A deque (double-ended queue) supports O(1) append and pop on both ends. A list supports O(1) on the right end but O(n) on the left. Use a deque when you need a queue or a sliding window. The deque also has a maxlen parameter that auto-evicts when full. Perfect for ring buffers.

Q39. When would you use itertools.chain vs the + operator?

+ materializes a new list. O(n+m) time and memory. itertools.chain returns a lazy iterator with constant memory until iteration consumes it. For large lists or when you only need to iterate once, chain is the right call.

Python algorithm interview questions (8 Q)

These are the algorithm patterns most commonly asked with Python-specific idiom expectations. Strong candidates use language idioms; weak candidates write Java-in-Python.

Q40. Two-sum. Use a hash map for O(n) lookup.

def two_sum(nums, target):
    seen = {}
    for i, n in enumerate(nums):
        if target - n in seen:
            return [seen[target - n], i]
        seen[n] = i

Note: enumerate (not range(len(nums))). Dict lookup (not nested loop).

Q41. Reverse a string. s[::-1] is the one-line answer. The follow-up: how would you do it in-place on a list? Two-pointer swap.

Q42. Check if a string is a palindrome. s == s[::-1] for the simple case. For "ignore case and non-alphanumeric": import re; cleaned = re.sub(r'[^a-z0-9]', '', s.lower()); return cleaned == cleaned[::-1].

Q43. Find the longest substring without repeating characters. Sliding window with a set or dict tracking last-seen index.

Q44. Detect a cycle in a linked list. Floyd's tortoise-and-hare. Two pointers, one moving twice as fast. If they meet, there's a cycle.

Q45. Binary search. import bisect for the built-in version. The interviewer usually wants you to implement it from scratch. Reach for bisect only if they say it's fair game. Master both the lower-bound and upper-bound variants.

Q46. K-th largest element. heapq.nlargest(k, nums)[-1] is the one-liner. Implementing a min-heap of size k from scratch is the deeper version. O(n log k) time, O(k) space.

Q47. Merge two sorted lists. Two pointers, build the result. With generators, you can write heapq.merge(a, b) for the lazy version that works on iterables of any length.

Pandas / NumPy interview questions (5 Q)

For data engineer and data analyst roles. Cross-cluster with the data engineer interview questions guide.

Q48. What's the difference between a pandas Series and a DataFrame?

A Series is a 1D labeled array (like a single column). A DataFrame is a 2D labeled structure (like a table). A DataFrame is essentially a dict of Series sharing an index.

Q49. How do you filter rows in a DataFrame?

Boolean indexing: df[df['col'] > 5]. Multiple conditions: df[(df['a'] > 5) & (df['b'] < 10)]. Use & and |, not and and or, and parenthesize each condition.

Q50. What's the difference between merge and join in pandas?

merge joins on column values (SQL-style). join joins on the index by default. merge is more flexible (specify left/right/inner/outer, multiple keys). join is convenient when you've already set indexes.

Q51. How is NumPy faster than a Python list?

NumPy uses contiguous C-allocated arrays with a single dtype, vectorized operations in C, and SIMD where available. A loop over a million ints in pure Python takes seconds. The equivalent NumPy operation takes milliseconds. The cost is memory homogeneity. All elements must share a dtype.

Q52. What does axis=0 vs axis=1 mean in pandas?

axis=0 operates down rows (column-wise reductions). axis=1 operates across columns (row-wise reductions). The mnemonic: axis=0 collapses rows, axis=1 collapses columns. df.mean(axis=0) gives one mean per column.

How to prepare for a Python interview (6 steps)

A focused three-week prep plan, scaled for a CS new grad whose Python is already conversational but who hasn't drilled the language-specific concepts. Adjust if your starting point differs.

  1. Week 1: drill the seven language-specific concepts. Decorators, generators, context managers, the GIL, dunder methods, MRO, and duck typing. Spend 60-90 minutes on each, writing at least one example from scratch. Read the official documentation, not third-party blog posts. The docs are the source interviewers reference.

  2. Week 2: solve 40-50 algorithm problems using Python idioms. Pick a curated list (Blind 75 or NeetCode 150) and solve them in Python idiomatically. Reach for enumerate, zip, comprehensions, collections.Counter, defaultdict, and heapq when they fit. Time yourself: 20 minutes per Medium, 35 per Hard.

  3. Week 2 in parallel: memorize complexity for the four core data structures. Lists, tuples, dicts, sets. Write the table on one page. Practice stating it out loud while coding so the answer comes automatically when an interviewer asks.

  4. Week 3: practice OOP questions. Inheritance, MRO, classmethod vs staticmethod vs instance method, @property, __init__ vs __new__, dunder methods. Build a small class hierarchy and exercise each concept on it.

  5. Week 3: run 3 timed mock interviews. End-to-end, 45 minutes each, on the canonical questions from this guide. Narrate your reasoning out loud while coding. Silent coding is a known anti-pattern in live rounds.

  6. Morning of the interview: warm up with your cheat sheet. Five minutes of review on the top 20 idioms with complexity. The act of writing the sheet from memory was the prep. The sheet itself is the warmup.

Python interview format by role type

The same Python language gets tested differently depending on what role you're interviewing for. The breakdown for the five most common roles asking Python interviews in 2026:

RoleAlgorithm depthOOP depthAsync / GIL focusStandard libraryPandas / NumPyDomain extras
Software Engineer (SWE)High (Blind 75 bar)MediumMediumMediumLowWeb framework (Flask / FastAPI / Django)
Data EngineerMedium (SQL-heavy)LowMedium-High (async pipelines)HighHighSQL, Spark, distributed systems
Data ScientistLowLowLowMediumHighStatistics, ML model design
DevOps / SREMediumLowHigh (process management)High (subprocess, logging)NoneLinux, Docker, networking
ML EngineerMediumMediumHigh (data parallelism)MediumHighPyTorch / TensorFlow, model serving

Two patterns to notice. First, every role tests the standard library at moderate depth. collections, itertools, functools are universal. Second, async and GIL questions concentrate on the roles where multi-process or multi-threaded code is the daily work (data engineering, DevOps, ML engineering). If you're interviewing for a SWE role at a web-heavy company, you can deprioritize the GIL deep-dive in favor of OOP and framework knowledge.

Python interview cheat sheet

A one-page reference of the top 20 idioms, organized for the morning-of warmup. The act of writing this from memory is the prep; carrying it into the interview is the safety net.

#IdiomUse caseComplexity
1enumerate(lst)Loop with indexO(n)
2zip(a, b)Parallel iterationO(min(len(a), len(b)))
3[x for x in lst if cond]Filter and transformO(n)
4(x for x in lst)Lazy iteratorO(1) per yield
5dict.get(k, default)Safe lookupO(1) avg
6collections.defaultdict(list)Auto-init valuesO(1) avg
7collections.Counter(lst)Frequency countO(n)
8collections.deque()O(1) both-ends queueO(1) push/pop
9heapq.heappush / heappopMin-heap operationsO(log n)
10heapq.nlargest(k, lst)Top-k elementsO(n log k)
11sorted(lst, key=lambda x: x[1])Custom sortO(n log n)
12lst.sort(key=..., reverse=True)In-place sortO(n log n)
13set(lst)Dedupe, O(1) membershipO(n) build
14s[::-1]Reverse string or listO(n)
15' '.join(parts)Concatenate stringsO(n)
16f"{var} is {x}"String interpolationO(1)
17itertools.chain(a, b)Lazy concatenationO(1) per yield
18functools.lru_cacheMemoize pure functionO(1) per cache hit
19bisect.bisect_left(lst, x)Binary search in sortedO(log n)
20with open(path) as f:Auto-close resourceO(1) overhead

Memorize the top half; the bottom half is the polish.

How to handle Python tricky questions you've never seen

The reality of a Python interview is that you will hit at least one question you haven't seen. A behavior, a built-in method, an edge case in the standard library. The candidate who freezes loses the round. The candidate who reasons through it out loud often passes even when they get the wrong answer.

A four-step pattern for handling unfamiliar questions:

1. Restate the question in your own words. Slow down. Confirm what's being asked. Half the "tricky" questions become normal once you say them back. Example: "So you're asking what happens when I subclass int and override __add__. Would that change how 1 + 2 behaves? Let me think about that." That sentence buys you 10 seconds of thinking time and signals careful reasoning.

2. State what you know and what you don't. Don't pretend. "I know __add__ is called for +, but I'm not 100% sure whether subclassing int overrides the operator at the C level or only at the Python level." Calibration beats confidence. Interviewers reward honest uncertainty more than they punish a wrong guess.

3. Reason from first principles. If you don't remember the answer, derive it. "Operators in Python dispatch to dunder methods. If my subclass defines __add__, instances of my subclass should use it. But 1 + 2 uses int.__add__ directly, so my subclass wouldn't affect it." That trail of reasoning is the work the interviewer is grading.

4. Test the hypothesis if you can. "Can I open a REPL and check?" is sometimes welcome and sometimes not, depending on the round. If allowed, do it. If not, walk through it on the whiteboard or in the editor with comments.

The pattern works because tricky Python questions are rarely about memorization. They're about whether you understand the underlying model: operator dispatch, MRO, the difference between __new__ and __init__, what with actually compiles to. Show your reasoning and you show your understanding.

Common Python interview mistakes for CS new grads

The seven most-reported mistakes from new-grad Python interviews in the 2025-2026 hiring cycle, in roughly the order of frequency:

Writing Java-in-Python. for i in range(len(arr)): print(arr[i]) instead of for x in arr: print(x). Initializing an empty list and appending in a loop instead of using a comprehension. Using a verbose counter dict instead of collections.Counter. The interviewer sees: candidate used Python but didn't learn Python.

Confusing is and ==. Comparing strings or integers with is. Sometimes it works (small-integer caching) and sometimes it doesn't, which is the mark of someone who's hit the gotcha but doesn't understand why.

Not knowing what range does in Python 3. range(10**6) is lazy and uses constant memory. If you treat it like a list (e.g., subscript it and assume the list is materialized), you're working from a Python 2 mental model.

Mutable default arguments. def f(x=[]) is the canonical gotcha. The default list is created once at function-definition time and shared across calls. The interview-relevant fix: use None as the sentinel and create the list inside the function.

Bare except: clauses. Catches KeyboardInterrupt and SystemExit, which you almost never want to swallow. Always catch a specific exception type or at minimum except Exception:.

Not preserving function metadata in decorators. Skip functools.wraps and your decorated function loses its __name__, __doc__, and __qualname__. The interviewer is checking whether you've shipped a decorator into a real codebase or only seen one in a tutorial.

Forgetting that dicts are insertion-ordered in 3.7+. Some candidates still believe dict iteration order is unspecified. As of Python 3.7 it's a language guarantee. Knowing this is a small signal that you've kept up with the language.

One thing I'd add from watching new grads do this: don't try to memorize all seven the night before. Pick the two that match how you've been writing Python in coursework (almost always Java-in-Python and bare except) and audit your last LeetCode solutions for those patterns. Fix them in your muscle memory. The other five take care of themselves once those two are gone.

Key terms

GIL (Global Interpreter Lock)
The mutex inside CPython that lets only one thread execute Python bytecode at a time. The reason multithreaded CPU-bound code in CPython doesn't get faster on more threads, and the reason you reach for multiprocessing or compiled extensions instead.
Decorator
A callable that wraps a function (or class) to add behavior: logging, caching, timing, registration. The @decorator syntax is sugar for f = decorator(f). Almost every Python framework uses them heavily.
Generator vs Iterator
A generator is a function with yield that produces values lazily. Calling it returns a generator object. An iterator is any object with __iter__ and __next__ methods. All generators are iterators. Not all iterators are generators (you can write an iterator class manually).
Context manager + the with statement
An object with __enter__ and __exit__ methods that manages setup and teardown of a resource. The with statement guarantees __exit__ runs even on exception. The canonical pattern for files, locks, database connections, and any resource with a lifecycle.
MRO (Method Resolution Order)
The order Python searches parent classes when looking up a method on a class with multiple inheritance. Computed by the C3 linearization algorithm. Inspect with ClassName.__mro__. Determines how super() resolves in diamond-inheritance shapes.
Duck typing
The principle that an object's suitability for an operation depends on whether it has the required methods, not on its inherited type. "If it walks like a duck and quacks like a duck, it's a duck." Python's default disposition; statically type-checkable with Protocols (PEP 544).
Mutable vs immutable
A mutable object can be changed after creation (lists, dicts, sets). An immutable object cannot (ints, floats, strings, tuples, frozensets). Only immutable objects are hashable, and only hashable objects can be dict keys or set members. The most common source of beginner bugs is assuming a list is shared by value when it's actually shared by reference.

Related guides


About the author: Alex Chen is the founder of InterviewChamp.AI, building AI interview prep for the new-grad CS market and writing about the modern interview gauntlet from the inside.

Related guides

Interview Process

System Design Interview Guide for CS New Grads (2026): Framework, Templates, Cheat Sheet

The new-grad system design interview is a vocabulary check, a structure check, and a communication check, not a senior architect evaluation. This guide gives you a 4-step framework, a 12-template cheat sheet, a 45-minute time budget, the five canonical problems that carry 80% of new-grad rotations, and a side-by-side of HLD vs LLD vs machine-learning-system-design. Built for the CS new grad who has solved 600 LeetCode problems but never drawn a load balancer.

Alex Chen ·

Read more →
Interview Process

The 2026 CS New-Grad Interview Loop: Phone Screen to Offer at Every Tier

The 2026 CS new-grad interview loop runs five steps (recruiter screen, technical screen, onsite, debrief, offer) but the shape of each step now depends on tier of company. This guide maps the loop for FAANG, mid-tier public, startup, consultancy, and research lab, with 2026 timelines and how AI-fraud concerns brought in-person rounds back.

Alex Chen ·

Read more →
Interview Process

Accounting Interview Questions for 2026: 40+ Questions for Staff Accountants, Big 4 Candidates, and CPA Pivots

Accounting interview questions in 2026 test six things at once: do you know GAAP cold, can you walk a transaction from journal entry to the three financial statements, can you read a balance sheet under pressure, do you understand the difference between Big 4 audit and corporate close work, can you handle the behavioral round without sounding rehearsed, and can you reason through a case study when the prompt is intentionally vague. If you're an accounting grad, a CPA candidate, or pivoting from finance/ops into staff accountant work, the technical bar isn't the killer. It's framing what you know in 60 seconds while a senior manager watches you on Zoom. This guide walks 40+ questions across six categories, the Big 4 vs corporate vs public-accounting split, and the four-week prep plan that actually works.

Alex Chen ·

Read more →

Frequently asked questions

What Python interview questions should I prepare for in 2026?
Prepare across seven categories: data structures (lists, tuples, sets, dicts and their time complexity), object-oriented programming (classes, inheritance, MRO, dunder methods), decorators, generators and iterators, async and concurrency (the GIL, asyncio, threading, multiprocessing), standard-library idioms (collections, itertools, functools), and algorithm patterns with Python-specific idioms. Most new-grad Python interviews cover 30-40% data structures, 20% OOP, 20% algorithms, and the remaining 20% on language-specific concepts where the GIL, decorators, and generators get the most attention.
What's the difference between a list and a tuple in Python?
A list is mutable and a tuple is immutable. Lists use square brackets and support append, extend, pop, and slice assignment; tuples use parentheses and are fixed at creation. Tuples can be used as dictionary keys and set members because they are hashable; lists cannot. Tuples are also slightly faster to create and iterate over because the interpreter can allocate a single contiguous block. The interview-relevant takeaway is that immutability is the design intent of tuples. They signal that the data is a record, not a sequence.
What is the GIL in Python?
The GIL (Global Interpreter Lock) is a mutex inside CPython (the reference Python interpreter) that allows only one thread to execute Python bytecode at a time. It exists because CPython's memory management is not thread-safe, and the GIL is the simplest way to keep reference counts consistent across threads. The practical consequence is that CPU-bound Python code does not get faster on multiple threads. For CPU-bound parallelism you reach for multiprocessing or compiled extensions; for I/O-bound concurrency, threading and asyncio both work because they release the GIL while waiting on I/O. Note that PEP 703 introduced an optional free-threaded build of CPython in 3.13, but most production environments in 2026 still run with the GIL enabled.
What is a Python decorator?
A decorator is a callable that takes a function and returns a function. Typically a new function that wraps the original with extra behavior. Decorators are syntactic sugar for the pattern `f = decorator(f)`, applied with the @ symbol above the function definition. Common uses include logging, caching, access control, and timing. The deeper interview question is usually about preserving the wrapped function's metadata using `functools.wraps`, writing a decorator that accepts arguments (which requires three levels of nesting), and understanding that class methods can also be decorated.
What is the difference between yield and return in Python?
`return` exits the function and returns a value; `yield` pauses the function, returns a value to the caller, and remembers where it stopped so it can resume on the next call. A function with at least one `yield` is a generator function. Calling it returns a generator object rather than running the body. The generator only runs when iterated. The memory implication is the headline: a list comprehension materializes every element in memory; a generator expression streams them one at a time. For large datasets, generators are the difference between an out-of-memory crash and a clean iteration.
How does Python's garbage collection work?
CPython uses reference counting as the primary mechanism. Each object tracks how many references point to it, and when the count drops to zero the object is immediately deallocated. A generational garbage collector runs on top of that to catch reference cycles, which reference counting alone cannot reclaim (two objects pointing at each other). The interview-relevant nuance is that you can break a cycle manually by setting one reference to None, or by using weak references via the `weakref` module. The `gc` module exposes the collector for inspection and tuning.
What is the difference between asyncio, threading, and multiprocessing?
All three handle concurrency but solve different problems. `threading` runs multiple threads in a single process and shares memory; useful for I/O-bound work but limited by the GIL for CPU-bound work. `multiprocessing` spawns separate processes with separate memory; useful for CPU-bound parallelism because each process has its own interpreter and its own GIL. `asyncio` runs a single thread with cooperative coroutines; useful for high-concurrency I/O (thousands of network connections) where the overhead of thread context-switching becomes prohibitive. The decision tree: CPU-bound → multiprocessing, low-concurrency I/O → threading, high-concurrency I/O → asyncio.
What is __init__ vs __new__ in Python?
`__new__` is the constructor. It allocates the object and returns the new instance. `__init__` is the initializer; it sets up the instance after `__new__` has created it. For ordinary classes you only override `__init__`; `__new__` is rarely needed unless you're subclassing an immutable type (like `int`, `str`, or `tuple`), implementing a singleton pattern, or building a metaclass. The exam-worthy distinction is that `__new__` is a static method (it receives the class as its first argument) while `__init__` is an instance method (it receives the already-created instance).
What are dunder methods in Python?
Dunder (double-underscore) methods are special methods Python invokes implicitly for built-in operations. `__init__` runs on instance creation; `__str__` and `__repr__` are called by `print` and the REPL; `__len__` enables `len(obj)`; `__getitem__` enables `obj[key]`; `__iter__` and `__next__` enable iteration; `__eq__` and `__hash__` enable equality and use as a dict key; `__enter__` and `__exit__` enable use as a context manager. Implementing dunder methods is how you make your own classes behave like built-in types. It's the principle Python's documentation calls 'duck typing.' The interview question is often: name three dunder methods you've implemented in a real project and what they did.
What is the difference between a shallow copy and a deep copy?
A shallow copy creates a new container but the inner objects are the same references. Modifying a nested list inside a shallow copy modifies the original. A deep copy recursively copies every nested object, producing a fully independent tree. The `copy` module provides both: `copy.copy()` for shallow, `copy.deepcopy()` for deep. The interview-relevant case is mutable defaults. `def f(x=[])` is a classic Python gotcha because the default list is created once at function-definition time and shared across calls. Using `None` and creating the list inside the function is the canonical fix.
How do you handle exceptions in Python?
Use `try/except/else/finally`. `try` wraps the code that might raise; `except` catches specific exception types (always specific, never bare `except:`); `else` runs only if no exception was raised; `finally` always runs, used for cleanup. Custom exceptions inherit from `Exception` (not `BaseException`, which is for system-level interrupts). The 2026 best practice is to chain exceptions with `raise NewException(...) from original_exception` so the traceback preserves the cause. Context managers (`with` blocks) are the cleaner alternative when the cleanup is resource-oriented.
What are Python context managers and the with statement?
A context manager is an object that defines `__enter__` and `__exit__` methods to set up and tear down a resource. The `with` statement guarantees `__exit__` runs even if an exception is raised inside the block. That makes it the canonical pattern for files, locks, database connections, and any resource that must be released. The `contextlib` module provides `@contextmanager` to write context managers as generator functions (yield once between setup and teardown) instead of writing a full class. Use a context manager whenever the resource has a clear lifecycle; it's almost always cleaner than try/finally.
What is duck typing in Python?
Duck typing is the principle that an object's suitability for an operation is determined by whether it has the required methods, not by its inherited type. 'If it walks like a duck and quacks like a duck, it's a duck.' A function that calls `obj.read()` will work on any object with a `read` method, regardless of its class. Python prefers duck typing over the explicit type-checking of statically-typed languages. The 2026 nuance is that type hints (PEP 484, expanded by Protocols in PEP 544) give you the option of static-type-checking your duck types without giving up the runtime flexibility.
How should I prepare for a Python interview as a CS new grad?
Three weeks of focused work. Week 1: drill the language-specific concepts your coursework probably skipped. Decorators, generators, the GIL, context managers, dunder methods. Week 2: solve 40-50 LeetCode-style problems using Python idiomatically (`enumerate`, comprehensions, `collections.Counter`, `defaultdict`, `heapq`) rather than translating Java or C++ patterns. Week 3: run timed mock interviews on the canonical questions from this guide, narrating your reasoning out loud. The interview question depth is usually shallow for new grads but the language-specific surface area is wide. Knowing 20 concepts at moderate depth beats knowing 5 deeply.
What's the most common Python interview mistake new grads make?
Writing Python that looks like Java. Initializing an empty list and appending in a loop when a comprehension would do; using a counter dict when `collections.Counter` does it in one line; iterating with `range(len(arr))` when `enumerate(arr)` is cleaner; reaching for a class when a function would work. Interviewers grade idiom fluency, not just correctness. The candidate who knows Python well writes shorter, more readable code. The difference is visible inside two minutes of a coding round.