Interview questions

Python Interview Questions: 20 Answers for Junior and Mid-Level Screens

June 27, 2025Updated May 28, 202622 min read
Top 30 Most Common Interview Questions About Python You Should Prepare For

A prioritized playbook of the 20 Python interview questions that show up most in junior and mid-level screens, with concise model answers, common follow-up.

Most candidates preparing for a Python screen spend their time reviewing concepts they already know instead of drilling the questions that actually decide the outcome. The python interview questions that show up repeatedly in junior and mid-level screens aren't obscure — they're the same dozen topics, asked in slightly different ways, with a follow-up probe waiting on the other side of your first answer. The problem isn't knowledge. It's that candidates haven't practiced giving a tight, defensible answer under time pressure, and they haven't thought through what the interviewer will ask next.

This playbook covers the highest-frequency questions across basics, data structures, OOP, functions, and concurrency — with model answers, follow-up traps, and the specific phrasing that holds up when the interviewer pushes back.

Use This Playbook Like a Shortlist, Not a Textbook

Start With the Questions That Show Up Everywhere

Python interview prep fails when candidates treat it like studying for a comprehensive exam. A junior or mid-level screen isn't testing whether you've read the entire language reference — it's testing whether you can explain the core concepts clearly, pick the right tool for a simple problem, and hold up under a follow-up question. Prioritization matters more than completeness. If you have two hours before a screen, drilling the twenty questions in this guide will do more for you than reviewing Python's full data model.

The questions in this playbook aren't ranked arbitrarily. They're the ones that appear in the highest proportion of screens across backend, automation, and data engineering roles, based on what junior engineers consistently report being asked. Start there.

Answer in 60 Seconds Without Sounding Rehearsed

The formula that works under pressure is: claim → plain-English explanation → one concrete example. That's it. A 60-second answer built on that structure sounds confident without sounding scripted. The mistake candidates make is starting with the example and hoping the explanation emerges — it rarely does. State your claim first ("Lists are mutable, tuples aren't"), explain why that matters in plain English, then anchor it with a short code example or real scenario.

Research from Harvard Business Review on structured communication under pressure consistently shows that listeners retain the most when the main point leads. In an interview, that means your first sentence should already be the answer, not the wind-up to it.

Use the Follow-Up as the Real Test

The follow-up question is where most interviews actually get decided. A candidate who can answer "what's the difference between a list and a tuple?" is doing the minimum. An interviewer who hears a clean first answer will immediately ask "when would you actually choose one over the other?" or "what breaks if you use the wrong one?" If your answer to the first question doesn't contain the structural reasoning, you have nothing to say to the second.

In mock interviews, the pattern is consistent: short, confident answers that include a reason survive follow-ups. Long answers that cover every edge case often collapse when the interviewer changes the framing slightly, because the candidate was reciting rather than reasoning.

The Python Basics Interviewers Ask When They Want to See If You Actually Know the Language

These python interview questions look easy. They're not — they're filters. The interviewer isn't checking whether you know the word "interpreted." They're checking whether you know what it means in practice.

Is Python Compiled or Interpreted?

The interview-safe answer: Python is interpreted at runtime, but it does compile source code to bytecode first. When you run a `.py` file, CPython compiles it to `.pyc` bytecode and then the interpreter executes that bytecode. The common oversimplification to avoid is saying "Python is just interpreted" — that's technically incomplete and an interviewer who knows Python well will push back. The practical point is that you don't compile a binary ahead of time the way you would in C, which is why Python is slower for CPU-heavy work but faster to iterate on during development.

What Does Dynamic Typing Really Mean in Python?

The interview-safe answer: Dynamic typing means that types are attached to objects, not to variable names. A variable is just a name that points to an object, and that object has a type. You can rebind the name to a different type at any time. The trap here is saying "Python has no types" — it absolutely does. Every object has a type; you can check it with `type()` or `isinstance()`. What Python doesn't have is type declarations on variables. That's the distinction the interviewer wants to hear.

Why Does Indentation Matter So Much?

The interview-safe answer: Indentation in Python isn't a style preference — it's syntax. Where other languages use curly braces or keywords like `begin`/`end` to define blocks, Python uses indentation level. An `if` block, a `for` loop body, a function definition — all of these are delimited by consistent indentation. Mixing tabs and spaces, or inconsistent indentation depth, produces an `IndentationError` or, worse, a logic bug that doesn't raise an error. This is a language design choice, not a linter rule.

What Is the Difference Between Python 2 and Python 3?

The interview-safe answer: Python 2 reached end-of-life in January 2020, and almost every new project should use Python 3. The practical differences that come up in interviews are: `print` is a function in Python 3 (not a statement), string handling is Unicode by default in Python 3 (not ASCII), and integer division behaves differently — `5 / 2` returns `2.5` in Python 3 versus `2` in Python 2. The follow-up an interviewer might ask is whether you've worked on a Python 2 codebase and how you'd approach migration. The honest answer for most junior candidates is no, and that's fine — just know the key breaking changes. Python's official documentation covers the full list.

Lists, Tuples, Mutability, and Copy Questions Are Where People Slip

Lists vs Tuples: What Changes, What Doesn't, and Why Interviewers Care

The interview-safe answer: Lists are mutable — you can append, remove, or reassign elements after creation. Tuples are immutable — once created, their contents can't change. The practical reason to choose a tuple over a list is when you want to signal that the data shouldn't change: coordinates, RGB values, database row results. Tuples are also hashable (as long as their contents are), which means they can be used as dictionary keys or added to sets. Lists can't. That's the detail interviewers are listening for.

What Does Mutability Actually Mean?

The interview-safe answer: Mutability is about whether the object's state can be changed in place. When you append to a list, the list object itself is modified — the same object in memory now contains more elements. When you "change" a string, you're actually creating a new string object and rebinding the name to it. The subtle trap in interviews is confusing rebinding a name with mutating an object. Passing a mutable object into a function and modifying it inside the function changes the original object everywhere it's referenced — that's the real bug this question is probing for.

Shallow Copy vs Deep Copy: When the Bug Shows Up

The interview-safe answer: A shallow copy creates a new container object but doesn't copy the objects inside it — it copies references. So if you have a list of lists and make a shallow copy, both the original and the copy point to the same inner lists. Change an inner list through either reference and you see the change in both. A deep copy, via `copy.deepcopy()`, recursively copies every object, so you get a fully independent structure. The interview danger is code that looks safe — you made a copy, so you think you're working independently — until an inner object changes in both places. Python's `copy` module documentation covers the distinction precisely.

Show You Understand Identity, Equality, and the Traps Around Object Comparison

This category of Python coding interview questions is a classic filter for candidates who've used Python versus candidates who understand it.

What Is the Difference Between `is` and `==`?

The interview-safe answer: `==` tests value equality — do these two objects have the same value? `is` tests identity — are these two objects the same object in memory? Two separate lists with identical contents will pass `==` but fail `is`. The trap interviewers set is around small integers and interned strings: CPython caches integers from -5 to 256 and often interns short strings, so `a is b` might return `True` for small values even when you created them separately. That behavior is an implementation detail, not a language guarantee, and you should never rely on `is` to test value equality.

Why Do Two Equal-Looking Objects Sometimes Fail an Identity Check?

The interview-safe answer: Because `is` checks whether two names point to the exact same object in memory — not whether they contain the same data. `a = [1, 2, 3]` and `b = [1, 2, 3]` creates two separate list objects. `a == b` is `True` because the values match. `a is b` is `False` because they're different objects. The structural reason this question exists in interviews is to catch candidates who use `is` to compare strings or numbers in production code and get intermittent bugs because of CPython's caching behavior.

Functions, Scope, and the Little Syntax Questions Interviewers Love to Use as a Filter

What Do `args` and `*kwargs` Let You Do?

The interview-safe answer: `args` lets a function accept any number of positional arguments, collected into a tuple. `kwargs` lets it accept any number of keyword arguments, collected into a dict. The practical use case is wrapper functions and decorators — when you want to pass arguments through to another function without knowing what they are in advance. The follow-up trap is "when would you not* use them?" The honest answer: when your function has a clear, fixed signature, explicit parameters are better because they're self-documenting and easier to catch with a linter or type checker.

When Should You Use Lambda Instead of a Regular Function?

The interview-safe answer: Lambda is for small, single-expression functions that you're defining inline — typically as an argument to `sorted()`, `map()`, or `filter()`. The tradeoff to name explicitly: readability beats cleverness. A lambda that fits on one line and does one obvious thing is fine. A lambda with a conditional expression and nested calls is a maintenance problem. If the logic is more than one simple expression, write a named function. Interviewers want to hear that you know when not to use lambda, not just that you know the syntax.

What Does `pass` Actually Do?

The interview-safe answer: `pass` is a no-op — it does nothing and exists purely as a syntactic placeholder. Python requires a block to contain at least one statement, so `pass` satisfies that requirement when you want an empty function body, an empty class, or an empty branch. It's not an error handler, it's not a default return, and it's not equivalent to `continue` in a loop. Candidates who treat it as interchangeable with `return None` or `continue` are signaling they haven't thought carefully about what it actually does.

How Do Scope, Namespaces, and Name Resolution Work?

The interview-safe answer: Python resolves names using the LEGB rule — Local, Enclosing, Global, Built-in — in that order. When you reference a name inside a function, Python looks in the local scope first, then in any enclosing function scopes, then in the module-level global scope, and finally in built-ins. The debugging case this matters for: a nested function that reads a variable from its enclosing scope works fine, but if you try to assign to that variable without declaring it `nonlocal`, Python treats it as a new local variable and you get an `UnboundLocalError` if you read it before assigning. That's a subtle bug that shows up in real code. Python's language reference covers the full scoping model.

OOP Questions Are Really About Whether You Can Talk About Objects Without Hand-Waving

What Does `__init__` Actually Do?

The interview-safe answer: `__init__` is the initializer — it runs immediately after a new instance is created and sets up the instance's initial state by assigning attributes. It's not the constructor in the C++ sense; the object already exists when `__init__` runs. The actual object creation happens in `__new__`. Most Python interviews don't go deep on `__new__`, but knowing the distinction keeps you from saying `__init__` "creates" the object, which is technically wrong and an alert interviewer will notice.

Why Is `self` Everywhere?

The interview-safe answer: `self` is how Python passes the instance to its own methods. When you call `obj.method()`, Python translates that to `ClassName.method(obj)` — `self` is just the conventional name for that first argument. It's not a keyword; you could name it anything. The reason it's explicit, unlike `this` in Java or C++, is a Python design choice: explicit is better than implicit. Once you understand that `self` is just the instance being passed in, the syntax stops looking magical and starts looking obvious.

Class Variables vs Instance Variables: Where the Shared State Lives

The interview-safe answer: A class variable is defined on the class itself and shared across every instance. An instance variable is defined on `self` inside `__init__` and belongs to that specific instance. The bug interviewers want you to recognize: if a class variable is mutable — say, a list — and you append to it through one instance without overriding it, every instance sees the change. That's because they're all pointing to the same list object. Assigning a new value to the name through an instance creates an instance variable that shadows the class variable, which is a different behavior entirely.

When Would You Reach for Inheritance, and When Would You Not?

The interview-safe answer: Inheritance makes sense when the relationship is genuinely "is a" — a `Dog` is an `Animal`, a `SavingsAccount` is a `BankAccount`. Prefer composition when the relationship is "has a" — a `Car` has an `Engine`, a `Report` has a `Formatter`. The interview answer interviewers respect is the one that acknowledges inheritance's cost: tight coupling, fragile base class problems, and difficulty changing the hierarchy later. Composition is usually easier to test and easier to change.

Python Interview Questions About Data Structures Are Really About Choosing the Right Tradeoff

When Do You Use a List, Dict, Set, or Tuple?

The interview-safe answer: Use a list when order matters and you need indexed access or a mutable sequence. Use a dict when you need fast key-based lookup — O(1) average — and want to associate values with meaningful keys. Use a set when you need uniqueness and fast membership testing, like deduplicating a list of IDs. Use a tuple when the data is fixed and you want to signal that it shouldn't change, or when you need a hashable sequence. The practical anchor: if you're building a cache for API responses, a dict keyed on request parameters is the right call. A list would require a linear scan every time.

What's the Interview-Safe Way to Talk About Strings in Python?

The interview-safe answer: Strings are immutable sequences of Unicode characters. That immutability has a performance consequence: every time you concatenate strings in a loop with `+`, you're creating a new string object each iteration. For building strings from many pieces, `"".join(list_of_strings)` is significantly faster because it allocates once. Interviewers in backend or data roles will sometimes ask about this specifically, and knowing the reason — not just the rule — is what separates a strong answer from a memorized tip.

How Do Comprehensions Differ From Loops?

The interview-safe answer: A list comprehension is a concise, readable way to build a list from an iterable in a single expression: `[x * 2 for x in range(10) if x % 2 == 0]`. It's often faster than an equivalent `for` loop because the iteration happens in C under the hood in CPython. The tradeoff to name: comprehensions are clean for simple transforms and filters. They become a maintenance problem when the logic gets complex — nested comprehensions with conditions are hard to read and hard to debug. When the logic is more than one simple expression, a regular loop with clear variable names is better code.

Modern Python Questions Now Include Typing, Dataclasses, Testing, and Packaging

These python interview questions are increasingly common in backend and automation roles and often catch candidates who learned Python a few years ago and haven't kept up.

Why Use Type Hints If Python Is Dynamically Typed?

The interview-safe answer: Type hints don't change runtime behavior — Python ignores them at runtime. What they do is improve readability, enable static analysis tools like `mypy` and Pyright to catch bugs before you run the code, and make IDEs significantly more useful for autocomplete and refactoring. The follow-up interviewers ask: "What's `Optional`?" — it means the value can be either the specified type or `None`. Knowing that distinction signals you've actually used type hints in a real codebase, not just read about them. Python's `typing` module documentation is the primary reference.

When Would You Use a Dataclass Instead of a Hand-Written Class?

The interview-safe answer: A dataclass, via `@dataclass`, auto-generates `__init__`, `__repr__`, and `__eq__` based on the field annotations you declare. It's the right choice for simple data containers — a config object, a result struct, an API response model — where you'd otherwise write boilerplate. It's not the right choice when the class has complex initialization logic, invariants to enforce, or behavior that goes beyond storing and retrieving data. The interview answer that lands well: "I use dataclasses when the class is mostly data and I want the boilerplate handled for me, but I write regular classes when behavior is the point."

How Do pytest and unittest Fit Into an Interview Answer?

The interview-safe answer: `pytest` is the dominant choice for new Python projects because its test syntax is simpler — plain `assert` statements instead of `self.assertEqual` — and its fixture system is more flexible than `unittest`'s `setUp`/`tearDown`. For an interview, the practical framing is: write a test function, use a fixture to set up shared state, and assert the behavior of the function you're testing, not its implementation. A concrete example helps: "I'd test an API endpoint by calling the function with a mock HTTP request and asserting the response status and body."

What Do venv, pip, and requirements.txt Actually Solve?

The interview-safe answer: `venv` creates an isolated Python environment so your project's dependencies don't collide with system-level packages or other projects. `pip` installs packages into that environment. `requirements.txt` pins the exact versions of every dependency so anyone who clones the repo can reproduce your environment. The real interview context: if you've ever broken a local environment by upgrading a package for one project and breaking another, you understand exactly why isolation matters. This isn't abstract — it's the answer to a problem every Python developer hits eventually.

Concurrency Questions Separate Polished Memorization From Practical Understanding

What Is the GIL, in Plain English?

The interview-safe answer: The Global Interpreter Lock is a mutex in CPython that allows only one thread to execute Python bytecode at a time. It exists to protect CPython's memory management, which isn't thread-safe. The practical consequence: for CPU-bound work — number crunching, image processing — threading in CPython doesn't give you true parallelism because only one thread runs at a time. For I/O-bound work — waiting on network calls, disk reads — threading works fine because threads release the GIL while waiting. That's the distinction the interviewer wants to hear.

When Should You Use Threading?

The interview-safe answer: Threading is the right tool when your program spends most of its time waiting — on network responses, file I/O, database queries. While one thread waits, another can run. A concrete example: a script that downloads data from 20 API endpoints can use a thread per request and finish in roughly the time of the slowest single request, instead of the sum of all requests. The `concurrent.futures.ThreadPoolExecutor` is the modern way to manage this without writing raw thread management code.

When Is Multiprocessing the Better Answer?

The interview-safe answer: Multiprocessing bypasses the GIL by spawning separate processes, each with its own Python interpreter and memory space. That gives you true parallelism for CPU-bound work — data transformation, parsing large files, running simulations. The follow-up trap: multiprocessing adds real overhead. Spawning processes is expensive, and sharing data between them requires explicit serialization. It's not the magic fix for every slow program. If the task is small or the overhead of process startup exceeds the work saved, threading or async is the better choice.

How Do You Explain async and await Without Sounding Vague?

The interview-safe answer: `async`/`await` is Python's built-in support for cooperative concurrency within a single thread, using an event loop. When an `async` function hits an `await`, it pauses and yields control back to the event loop, which can run other coroutines while waiting. The practical use case: a web scraper that needs to fetch 100 pages. With async, you can fire off all 100 requests and process responses as they arrive, without blocking on each one. The key point interviewers want: async is about concurrency during waiting, not raw parallel speed. It doesn't make your CPU work faster. Python's asyncio documentation covers the event loop model in detail.

These Are the Follow-Up Traps Interviewers Use to See If Your Answer Is Real

Why Does That Matter in Production?

The interviewer who asks "why does that matter in production?" after your answer about shallow copies or the GIL is checking whether you've actually encountered the consequence or just read about it. The answer that works is a specific scenario: "A shallow copy of a nested config dict meant that when one service modified a nested setting, every service sharing that config saw the change — it took a while to find because the bug only appeared under concurrent load." You don't need to have lived that exact bug. You need to be able to reason about what would happen.

What Would Break If the Data Got Bigger?

Scale questions are often the real filter in mid-level screens. If your answer to a data structure question was "I'd use a list," the follow-up is "what happens when that list has a million items?" The right answer names the complexity: linear scan for membership testing becomes O(n), which matters when you're checking membership in a loop. A dict or set lookup stays O(1). Knowing the tradeoff and naming it — not just saying "it would be slow" — is what the interviewer is listening for.

How Would You Explain That to a Teammate?

The best Python interview answers are teachable. When an interviewer asks you to explain something to a hypothetical teammate, they're testing whether you understand it well enough to simplify it without losing the point. The difference between a crisp explanation and a jargon dump is whether you start with the concept or the consequence. "The GIL means that Python threads can't actually run in parallel for CPU work — so if you're trying to speed up a calculation, threading won't help and you need multiprocessing instead" is better than "the GIL is a mutex that serializes bytecode execution in CPython's memory management layer."

What Is the Safest Way to Recover If You Go Blank?

Panic in a technical screen is almost always a structure problem, not an intelligence problem. The recovery move: restate the question in your own words, answer the core in one sentence, then add the example. "So the question is about shallow versus deep copy — a shallow copy copies the container but not the contents, so inner objects are still shared. If I have a list of lists and shallow-copy it, changing an inner list changes it in both copies." That structure — restate, claim, example — gives you a scaffold to climb back onto when your mind goes blank. It works because it gives the interviewer something to respond to, which takes the pressure off you to fill the silence.

How Verve AI Can Help You Ace Your Software Engineer Coding Interview

The structural problem this playbook addresses — knowing the answers but collapsing under follow-up pressure — is exactly what practice in a static environment can't fix. Reading model answers builds recognition. What builds fluency is being asked the question live, giving an answer, and having something respond to what you actually said rather than a canned next prompt.

Verve AI Coding Copilot is built for that second layer. It reads your screen during a live technical round or practice session and surfaces real-time suggestions based on what's actually on the screen — the problem statement, your current code, the interviewer's follow-up. It works across LeetCode, HackerRank, CodeSignal, and live coding environments, so your practice translates directly to the format you'll face. The Secondary Copilot feature keeps a persistent view of one problem while you work, which matters when a Python concurrency question turns into a 20-minute implementation exercise and you need to hold context without losing your place. Verve AI Coding Copilot stays invisible during screen share, so it's there when you need it and out of the way when you don't. If you've drilled these 20 questions but still find yourself stalling on the follow-up, suggests answers live is the capability that changes the calculus — because the follow-up is where the interview actually starts.

Conclusion

A real technical screen moves fast. The interviewer asks, you answer, and before you've finished exhaling they're already asking why. The candidates who do well aren't the ones who reviewed the most material — they're the ones who practiced giving a clean first answer and built responses sturdy enough to survive the second question.

You now have the 20 highest-frequency Python interview questions, the model answers, and the follow-up traps. The next step is simple: go through each question aloud, give your answer without reading, and time yourself. The ones that stall you or run over 90 seconds are the ones to tighten. Do that once, fix the stalls, and you'll walk into the screen knowing exactly which ground you're standing on.

JM

James Miller

Career Coach

Ace your live interviews with AI support!

Get Started For Free

Available on Mac, Windows and iPhone