Python interview questions for freshers (with answers and code)
18 min readUpdated
These are the Python questions that come up again and again in fresher and campus interviews. Each answer is short enough to say out loud, and the tricky ones come with a small program. Every program here was run, and the output shown is the real output.
How to use this list
- Read the question and answer it out loud before you read the answer.
- For every program, guess the output first, then run it and check.
- If an answer feels new, open the linked lesson at the end. Interviewers ask follow-up questions.
Python basics
1. What is Python, and is it compiled or interpreted?
Python is a high-level, dynamically typed language. The usual implementation, CPython, first compiles your source into bytecode, then a virtual machine runs that bytecode. So it is both: compiled to bytecode, then interpreted. You do not run a separate compile step yourself.
2. What does dynamically typed mean? Is Python also weakly typed?
A variable has no fixed type; the object it points to has one. You can write x = 5 and later x = "five". Python is still strongly typed: it will not mix types silently, so "5" + 5 raises a TypeError.
3. What are mutable and immutable types? Give examples.
A mutable object can change after it is created: list, dict, set. An immutable object cannot: int, float, str, tuple, frozenset, bool. Changing an immutable value really creates a new object.
numbers = [1, 2, 3]
numbers.append(4) # changes the same list
print(numbers)
word = "cat"
try:
word[0] = "b" # strings cannot change
except TypeError as error:
print("TypeError:", error)
word = "b" + word[1:] # a new string
print(word)
Output
[1, 2, 3, 4] TypeError: 'str' object does not support item assignment bat
4. What is the difference between == and is?
== asks whether two objects have equal values. is asks whether they are the same object in memory. Use == for values. Use is only for singletons such as None: if x is None.
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # same values
print(a is b) # different objects
print(a is c) # same object
Output
True False True
5. Is Python pass by value or pass by reference?
Neither. Python passes a reference to the object, by value (often called pass by object reference or pass by assignment). If the function changes a mutable object, the caller sees it. If the function only rebinds the parameter name, the caller does not.
def add_item(items):
items.append("new") # changes the caller's list
def rebind(items):
items = ["other"] # only the local name changes
data = ["a"]
add_item(data)
print(data)
rebind(data)
print(data)
Output
['a', 'new'] ['a', 'new']
6. What are *args and **kwargs?
*args collects extra positional arguments into a tuple. **kwargs collects extra keyword arguments into a dict. The names args and kwargs are only a habit; the * and ** do the work.
def show(*args, **kwargs):
print(args)
print(kwargs)
show(1, 2, name="Asha", city="Pune")
Output
(1, 2)
{'name': 'Asha', 'city': 'Pune'}7. What is the mutable default argument problem?
A default value is created once, when the function is defined, not on every call. If the default is a list or dict, every call shares it. Use None as the default and create the object inside the function.
def bad(item, bucket=[]):
bucket.append(item)
return bucket
def good(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
return bucket
print(bad(1))
print(bad(2)) # surprise: the old list is reused
print(good(1))
print(good(2))
Output
[1] [1, 2] [1] [2]
8. What is the difference between a list and a tuple?
A list is mutable and a tuple is immutable. Because a tuple cannot change, it can be a dictionary key (if all its items are hashable) and is a good fit for fixed records such as (x, y). Lists are for collections that grow or change. See the full comparison guide for more.
9. What is a list comprehension? How is it different from a generator expression?
A list comprehension builds a whole list at once: [x * x for x in range(5)]. A generator expression uses round brackets and produces values one at a time, so it uses very little memory. Use a generator when you only loop over the result once, for example inside sum().
squares = [x * x for x in range(5)]
print(squares)
lazy = (x * x for x in range(5))
print(next(lazy))
print(next(lazy))
print(sum(lazy)) # adds the remaining values: 4 + 9 + 16
Output
[0, 1, 4, 9, 16] 0 1 29
10. What are append, extend and insert?
append(x) adds one item at the end. extend(iterable) adds every item of an iterable at the end. insert(i, x) adds at position i and shifts the rest, so it costs O(n).
items = [1, 2]
items.append([3, 4])
print(items)
items = [1, 2]
items.extend([3, 4])
print(items)
Output
[1, 2, [3, 4]] [1, 2, 3, 4]
11. What is slicing? How do you reverse a string or a list?
seq[start:stop:step] returns a new sequence. stop is not included. A step of -1 walks backwards, so seq[::-1] returns a reversed copy. For a list, list.reverse() reverses in place.
text = "placement"
print(text[0:5])
print(text[::-1])
print(text[-3:])
Output
place tnemecalp ent
12. What is the difference between sort() and sorted()?
list.sort() sorts the list in place and returns None. sorted(iterable) returns a new list and works on any iterable. Both are stable and accept key= and reverse=.
marks = [("Ravi", 72), ("Meena", 91), ("Tom", 72)]
print(sorted(marks, key=lambda m: m[1], reverse=True))
values = [3, 1, 2]
print(values.sort()) # sort() returns None
print(values)
Output
[('Meena', 91), ('Ravi', 72), ('Tom', 72)]
None
[1, 2, 3]Functions, scope and memory
13. Explain the LEGB rule.
Python looks up a name in this order: Local, Enclosing function, Global, Built-in. To assign to a global name inside a function you must say global name. To assign to a variable of an enclosing function use nonlocal name.
count = 0
def outer():
count = 10
def inner():
nonlocal count
count += 1
return count
return inner()
print(outer())
print(count) # the global is unchanged
Output
11 0
14. What is a lambda function?
A lambda is a small anonymous function written as one expression: lambda x: x + 1. It is handy as a key= function or a short callback. For anything longer, write a normal def.
15. What is a closure?
A closure is an inner function that remembers variables of the function that created it, even after that outer function has returned. Decorators and factory functions use closures.
def make_multiplier(factor):
def multiply(x):
return x * factor
return multiply
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5), triple(5))
Output
10 15
16. What is a decorator?
A decorator is a function that takes a function and returns a new function, usually adding behaviour before or after the call. @decorator above a def is shorthand for f = decorator(f). Use functools.wraps so the wrapped function keeps its name.
from functools import wraps
def log_call(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("calling", func.__name__)
return func(*args, **kwargs)
return wrapper
@log_call
def add(a, b):
return a + b
print(add(2, 3))
Output
calling add 5
17. What is a generator? What does yield do?
A generator function uses yield to hand back one value and pause. The next call to next() resumes from the same place with all local variables intact. Generators are lazy, so they can produce huge or endless sequences with constant memory.
def countdown(n):
while n > 0:
yield n
n -= 1
print(list(countdown(3)))
Output
[3, 2, 1]
18. What is the difference between a shallow copy and a deep copy?
A shallow copy (copy.copy, list.copy(), lst[:]) makes a new outer container but reuses the same inner objects. A deep copy (copy.deepcopy) copies the inner objects too. With nested lists, changing an inner list through a shallow copy changes the original as well.
import copy
original = [[1, 2], [3, 4]]
shallow = original.copy()
deep = copy.deepcopy(original)
original[0].append(99)
print(shallow)
print(deep)
Output
[[1, 2, 99], [3, 4]] [[1, 2], [3, 4]]
19. How does Python manage memory?
CPython uses reference counting: each object counts how many names point to it, and it is freed when the count reaches zero. A cyclic garbage collector also finds groups of objects that refer to each other but are no longer reachable. Python also keeps a private memory pool for small objects.
20. What is the GIL?
The Global Interpreter Lock is a lock in CPython that lets only one thread run Python bytecode at a time. So threads do not speed up CPU-heavy code, but they still help with I/O waits (network, files). For CPU-heavy work use multiprocessing. Newer Python releases have an optional free-threaded build, but the standard build still has the GIL.
Data structures and strings
21. How does a dictionary work? What can be a key?
A dict is a hash table. Python hashes the key to find its slot, so lookup, insert and delete are O(1) on average. A key must be hashable: immutable types such as int, str and tuples of hashable items. A list cannot be a key. Since Python 3.7, a dict remembers insertion order.
point = {(2, 3): "A"}
print(point[(2, 3)])
try:
bad = {[2, 3]: "A"}
except TypeError as error:
print("TypeError:", error)
Output
A TypeError: unhashable type: 'list'
22. What is a set? What are its main operations?
A set is an unordered collection of unique, hashable items with O(1) average membership tests. It supports union |, intersection &, difference - and symmetric difference ^. An empty set must be written set(), because {} is an empty dict.
a = {1, 2, 3, 4}
b = {3, 4, 5}
print(a | b)
print(a & b)
print(a - b)
print(a ^ b)
print(type({}))
Output
{1, 2, 3, 4, 5}
{3, 4}
{1, 2}
{1, 2, 5}
<class 'dict'>23. How do you remove duplicates from a list and keep the order?
Use dict.fromkeys(items). A dict keeps insertion order and keys are unique, so the keys come out in first-seen order. list(set(items)) also removes duplicates but loses the order.
items = [3, 1, 3, 2, 1]
print(list(dict.fromkeys(items)))
Output
[3, 1, 2]
24. Why are strings immutable? How do you build a long string efficiently?
Immutable strings can be shared safely and used as dictionary keys. Because each += may build a new string, doing it in a loop can be slow. Collect the pieces in a list and join once: "".join(parts).
parts = []
for i in range(5):
parts.append(str(i))
print("-".join(parts))
Output
0-1-2-3-4
25. What do enumerate and zip do?
enumerate(items) gives (index, item) pairs, so you do not need range(len(items)). zip(a, b) pairs items from several iterables and stops at the shortest.
names = ["Asha", "Ravi", "Meena"]
marks = [88, 72, 91]
for i, name in enumerate(names, start=1):
print(i, name)
print(dict(zip(names, marks)))
Output
1 Asha
2 Ravi
3 Meena
{'Asha': 88, 'Ravi': 72, 'Meena': 91}26. What values are falsy in Python?
False, None, zero (0, 0.0), and empty containers: "", [], (), {}, set(). Everything else is truthy. So write if items: instead of if len(items) > 0:.
Exceptions, files and modules
27. How does try / except / else / finally work?
Code in try runs first. If it raises, the matching except runs. else runs only if no exception happened. finally runs always, which makes it the right place for cleanup. Catch specific exceptions, not a bare except:.
def divide(a, b):
try:
result = a / b
except ZeroDivisionError:
print("cannot divide by zero")
else:
print("result is", result)
finally:
print("done")
divide(10, 2)
divide(1, 0)
Output
result is 5.0 done cannot divide by zero done
28. What is a context manager? Why use with?
A context manager sets something up and cleans it up for you, even if an error happens. with open(path) as f: closes the file automatically when the block ends. You can write your own with __enter__ and __exit__, or with contextlib.contextmanager.
29. What does if __name__ == "__main__": do?
When a file runs directly, Python sets __name__ to "__main__". When it is imported, __name__ is the module name. The check lets a file work as both a script and a module: the code under it runs only when the file is run directly.
30. What is the difference between a module and a package?
A module is one .py file. A package is a folder of modules (traditionally with an __init__.py). You import from both with import or from ... import ....
A few more that come up
31. What is the difference between @staticmethod and @classmethod?
A @classmethod receives the class as its first argument (cls), so it can build objects, which makes it good for alternative constructors. A @staticmethod receives neither the class nor the instance; it is just a function placed inside the class for organisation. See the OOP guide for examples.
32. What is PEP 8?
PEP 8 is the style guide for Python code: 4-space indentation, snake_case for functions and variables, PascalCase for classes, and lines of about 79 characters. Following it makes code easy for others to read. Tools such as black or ruff can format code for you.
33. What are map and filter? Are they better than a comprehension?
map(f, items) applies f to each item. filter(f, items) keeps items where f is true. Both return lazy iterators. Most Python code uses comprehensions instead because they are easier to read: [f(x) for x in items if cond(x)].
numbers = [1, 2, 3, 4, 5, 6]
print(list(map(lambda x: x * 10, numbers)))
print(list(filter(lambda x: x % 2 == 0, numbers)))
print([x for x in numbers if x % 2 == 0])
Output
[10, 20, 30, 40, 50, 60] [2, 4, 6] [2, 4, 6]
34. Why is 0.1 + 0.2 == 0.3 false?
Floats are stored in binary, and numbers like 0.1 cannot be stored exactly. The tiny error shows up in the sum. Compare floats with math.isclose(a, b), or use decimal.Decimal when you need exact decimal arithmetic such as money.
import math
from decimal import Decimal
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(math.isclose(0.1 + 0.2, 0.3))
print(Decimal("0.1") + Decimal("0.2"))
Output
0.30000000000000004 False True 0.3
35. How do you read a file safely?
Use with open(path, encoding="utf-8") as f: and loop over the file or call f.read(). Catch FileNotFoundError when the file may be missing. For paths, pathlib.Path is cleaner than joining strings by hand.
Tips for the interview itself
- Start with a one-line answer, then add a short example. Interviewers prefer clear over long.
- If you do not know, say how you would find out. An honest answer beats a confident guess.
- Expect follow-ups on anything you mention. Only bring up topics you can explain.
- Practise writing small programs in a plain editor. Many rounds do not give you an IDE.
Frequently asked questions
How many Python questions should a fresher prepare?
Know the 35 here well, with examples, rather than memorising hundreds of answers. Interviewers dig into a few topics. Depth matters more than count.
Which Python version do these programs need?
They run on Python 3.11 and newer, including 3.12 and 3.13.
Will interviewers ask me to write code?
Yes, usually. Expect small problems on lists, strings and dictionaries, and output-prediction questions like the ones above. Practise on paper or in a plain editor.
What should I study after these questions?
Do the OOP questions, then the collections comparison, then practise DSA problems. The linked lessons teach each topic step by step.
Learn it step by step
- Python Basics and How It Runs: Interview Questions
- Mutability, References and Copying: Interview Questions
- Functions, Scope and Closures: Interview Questions
- Exceptions and Files: Interview Questions
- Dicts, Sets and Hashing
- Decorators and Closures
- Iterators and Generators
- Output Puzzles: Lists, Aliasing and the Default-Argument Trap
More interview questions by topic
Practise this, step by step
Short lessons with quizzes, practice and interview questions, from your first program to job-ready.