⚡ Play a quiz
HomeInterview questions › Python
25 questions with answers

Python Interview Questions and Answers for Freshers

25 questions, written and maintained by the JBattle team · Last updated

Python interviews test whether you understand the language's model — how names bind to objects, what mutability implies, how iteration is lazy — rather than syntax. These are the questions that come up, with the traps interviewers use to check.

🎤 Practise these in an AI mock interview
Questions
25
Basic
9
Intermediate
12
Advanced
4

Data types and mutability

Where most Python follow-ups originate.

Basic
Q1

What is the difference between a list and a tuple?

A list is mutable, a tuple is not. That has consequences beyond editing: a tuple can be a dictionary key or a set member because it is hashable, it is slightly smaller and faster, and it signals to a reader that the contents are fixed. Use a tuple for a record of fixed shape, a list for a collection you will change.
Basic
Q2

What is the difference between a set and a dictionary?

Both are hash tables with O(1) average membership. A set stores keys only and is the right answer to "have I seen this?"; a dictionary maps keys to values. Both require keys to be hashable, so a list cannot be one and a tuple can.
Intermediate
Q3

What is the mutable default argument trap?

A default value is evaluated once, when the function is defined — not on each call. So a mutable default is shared by every call, and it accumulates. The fix is to default to None and create the object inside the function.
def add(item, basket=[]):        # wrong: one list, shared forever
    basket.append(item)
    return basket

add('a')   # ['a']
add('b')   # ['a', 'b']  <- surprise

def add(item, basket=None):      # correct
    basket = [] if basket is None else basket
    basket.append(item)
    return basket
The follow-upThis is the most-asked Python trap question. Being able to explain why — defaults are evaluated at definition time — matters more than knowing the fix.
Basic
Q4

What is the difference between `is` and `==`?

== compares values; is compares identity — whether both names refer to the same object. Small integers and short strings are cached, so is appears to work on them and then fails on larger values. Use is only for singletons: x is None.
Intermediate
Q5

What is the difference between a shallow and a deep copy?

copy.copy() duplicates the outer object but shares the nested ones, so mutating a nested list is visible through both. copy.deepcopy() duplicates recursively. Slicing (lst[:]) is a shallow copy too — a frequent source of surprise with lists of lists.
Intermediate
Q6

How do Python's *args and **kwargs work?

*args collects extra positional arguments into a tuple; **kwargs collects extra keyword arguments into a dict. At a call site the same symbols do the reverse — they unpack a sequence or a mapping into arguments. They are what let a decorator wrap a function of any signature.

Functions, decorators and generators

The intermediate round — asked to see whether you write Python or write Java in Python.

Intermediate
Q7

What is a decorator?

A function that takes a function and returns a replacement, used to add behaviour — logging, timing, caching, access checks — without editing the original. The @ syntax is shorthand for reassigning the name to the wrapped version.
import functools, time

def timed(fn):
    @functools.wraps(fn)          # keeps the original name and docstring
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        try:
            return fn(*args, **kwargs)
        finally:
            print(f"{fn.__name__} took {time.perf_counter() - start:.3f}s")
    return wrapper

@timed
def slow(): ...
The follow-upWhy functools.wraps? Without it the wrapper replaces the function's name, docstring and signature, which breaks introspection and confuses every debugging session afterwards.
Intermediate
Q8

What is a generator, and why use one?

A function that uses yield instead of return, producing values one at a time and suspending in between. It holds one item in memory rather than the whole sequence, so it can process a file larger than RAM, or an infinite stream. The cost is that it can only be consumed once.
def read_lines(path):
    with open(path) as f:
        for line in f:            # lazy: one line at a time
            yield line.rstrip()

# memory stays flat no matter how large the file is
count = sum(1 for line in read_lines('huge.log') if 'ERROR' in line)
Intermediate
Q9

What is the difference between a list comprehension and a generator expression?

Identical syntax except for the brackets. A list comprehension builds the whole list immediately; a generator expression produces items on demand. When you are aggregating — sum, any, max — the generator is the better choice, because the list you build is thrown away anyway.
Advanced
Q10

What is the difference between an iterator and an iterable?

An iterable can produce an iterator: it implements __iter__. An iterator produces the next value: it implements __next__ and raises StopIteration when exhausted. A list is iterable but is not an iterator, which is why you can loop over it repeatedly; a generator is its own iterator, which is why you cannot.
Basic
Q11

What does the `with` statement do?

It manages a context: the object's __enter__ runs on entry and __exit__ on exit, including when the body raises. It is how files get closed and locks released without a try/finally at every call site.

Runtime, OOP and performance

The questions that separate scripting familiarity from understanding.

Advanced
Q12

What is the GIL, and what does it mean for you?

The Global Interpreter Lock lets only one thread execute Python bytecode at a time in CPython. So threads do not speed up CPU-bound work — but they do help I/O-bound work, because the lock is released while waiting on the network or disk. For CPU-bound parallelism use multiprocessing, which runs separate interpreters.
The follow-upThe practical rule interviewers want: threads for I/O, processes for CPU.
Advanced
Q13

How does Python manage memory?

Primarily by reference counting: an object is freed the moment its count drops to zero, which makes cleanup prompt and predictable. Because reference counting cannot free cycles, a generational garbage collector runs periodically to find and collect them.
Intermediate
Q14

What is the difference between @staticmethod and @classmethod?

A @classmethod receives the class as its first argument, so it can construct instances of the actual subclass — which is what makes it right for alternative constructors like from_json. A @staticmethod receives nothing implicit; it is a plain function that lives in the class for organisation.
Basic
Q15

What is `self`, and why must it be written explicitly?

It is the instance, passed as the first argument to every instance method. Python makes it explicit rather than implicit — the language's stated preference for being obvious over being magic — which is also why a method can be called as Class.method(instance).
Advanced
Q16

How would you speed up a slow Python loop?

First measure — cProfile or timeit, never a guess. Then, in order of return: use the right data structure (a set for membership turns an O(n²) scan into O(n)); move the work into built-ins and comprehensions, which run in C; use a library that vectorises it, such as NumPy; and only then reach for multiprocessing or a compiled extension.

Everyday Python

The questions that check you have written real Python, not just studied it.

Basic
Q17

How do you merge two dictionaries?

a | b from Python 3.9, or {**a, **b} before that. In both, keys in b win. a.update(b) does it in place and returns None — assigning its result is a common slip.
Basic
Q18

What is an f-string, and why prefer it?

String interpolation with expressions inline: f"{name} scored {score:.2f}". It is faster than % and .format(), reads in the order it prints, and supports format specifiers and, since 3.8, f"{value=}" for debugging, which prints both the expression and its value.
Intermediate
Q19

How do you sort a list of dictionaries by a field?

sorted(items, key=lambda d: d['score'], reverse=True), or operator.itemgetter('score') which is faster. Python's sort is stable, so sorting twice — by the secondary key first, then the primary — gives a correct multi-level sort.
from operator import itemgetter

rows.sort(key=itemgetter('name'))                    # secondary key first
rows.sort(key=itemgetter('score'), reverse=True)     # then primary - stable
Intermediate
Q20

When would you use a deque instead of a list?

When you pop or append at the front. list.pop(0) is O(n) because every remaining element shifts; collections.deque gives O(1) at both ends. It is the right structure for a queue, a sliding window, or a bounded history with maxlen.
Basic
Q21

What is the difference between a module and a package?

A module is a single .py file. A package is a directory of modules, historically marked by __init__.py. Both are imported the same way; a package just adds a namespace level.
Basic
Q22

What is a virtual environment, and why does every project need one?

An isolated directory with its own interpreter and installed packages, so two projects can depend on different versions of the same library without conflict — and so a global install never silently changes what your project runs against. python -m venv .venv creates one.
Intermediate
Q23

How do you handle exceptions well in Python?

Catch the specific exception, never a bare except: — that swallows KeyboardInterrupt and hides real bugs. Keep the try block to the line that can actually fail. Use else for the code that runs only when nothing was raised, and finally for cleanup. When re-raising with context, raise NewError(...) from e preserves the original traceback.
Intermediate
Q24

What are type hints, and do they do anything at runtime?

Annotations describing expected types. Python does not enforce them at runtime — they are for readers, editors and a checker such as mypy. Their real value shows up in a codebase large enough that you cannot remember what a function returns, which is exactly when a bug is expensive.
Intermediate
Q25

How would you read a very large file without running out of memory?

Iterate over the file object, which yields one line at a time and never loads the whole thing — for line in f:. Combine it with a generator pipeline so filtering and transforming stay lazy too. f.read() and f.readlines() both pull the entire file into memory and are the wrong answer here.

Reading answers is not the same as giving them

Most candidates know the material and still stumble when asked out loud. Take a Python mock interview where the AI follows up on what you actually say.

🎤 Start a Python mock interview

Other interview question sets

Java
Java interview questions with real answers
30 questions
JavaScript
JavaScript interview questions with real answers
26 questions
SQL
SQL interview questions with real answers and queries
25 questions
React
React interview questions with real answers
23 questions
Spring Boot
Spring Boot interview questions with real answers
24 questions
DSA
DSA interview questions with real answers
24 questions
System Design
System design interview questions with real answers
23 questions