What you'll learn
Quick Answer
Fresher Python interviews focus on data structures and their trade-offs, mutability, comprehensions, functions including *args and decorators, generators and iterators, OOP basics, and exception handling. The questions that separate candidates are the mutable default argument, shallow versus deep copy, and how is differs from ==, because each one tests whether you understand references rather than syntax.
Data Structures and Their Trade-offs
List vs tuple?
Lists are mutable, tuples are not. Because tuples are immutable they can be dictionary keys and set members, and they are slightly faster and smaller. Use a tuple when the collection is a fixed record, a list when it will change.
When would you use a set?
For membership testing and removing duplicates. The key point to state is complexity: in on a set is O(1) average because it hashes, while in on a list is O(n).
if x in big_list: # O(n)
if x in big_set: # O(1) — turn the list into a set first if you check repeatedlyHow is a dictionary implemented?
As a hash table. Keys must be hashable, which in practice means immutable — that is why a list cannot be a key but a tuple can. Since Python 3.7, dictionaries preserve insertion order as a language guarantee.
What is the difference between is and ==?
== compares values; is compares identity — whether they are the same object in memory.
a = [1, 2]; b = [1, 2]
a == b # True
a is b # False — two distinct objectsUse is only for None, True and False. Mention that small integers and short strings are cached, so is may appear to work on them and then fail unpredictably.
Mutability — Where the Real Questions Are
What does this print, and why?
def add_item(item, items=[]):
items.append(item)
return items
print(add_item('a')) # ['a']
print(add_item('b')) # ['a', 'b'] — not ['b']The default is evaluated once, when the def statement runs, not on each call. So every call using the default shares one list. The fix:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return itemsThis is the single most-asked Python interview question, and it tests references rather than syntax.
Shallow vs deep copy?
import copy
shallow = copy.copy(original) # nested objects still shared
deep = copy.deepcopy(original) # fully independentSlicing (a[:]) and list() also give shallow copies, which is why changing a nested list in a "copy" changes the original.
Are arguments passed by value or reference?
Neither, strictly — Python passes references to objects by value. Reassigning a parameter inside a function does not affect the caller, but mutating a mutable argument does. Demonstrating that distinction is a strong answer.
Functions, *args and Decorators
What are *args and **kwargs?
*args collects extra positional arguments into a tuple; **kwargs collects extra keyword arguments into a dict. The asterisks are the syntax, the names are convention.
def f(a, *args, **kwargs): ...
f(1, 2, 3, x=4) # a=1, args=(2,3), kwargs={'x':4}What is a lambda and when should you use one?
An anonymous single-expression function, useful as a short key or callback. If it needs a statement or a name, write a normal function.
sorted(students, key=lambda s: s['marks'])What is a decorator?
A function that takes a function and returns a modified one, applied with @. Give a real use — timing, logging, authentication, caching.
def timer(fn):
def wrapper(*args, **kwargs):
start = time.time()
result = fn(*args, **kwargs)
print(f'{fn.__name__} took {time.time() - start:.2f}s')
return result
return wrapper
@timer
def slow(): ...Mention functools.wraps, which preserves the original function's name and docstring — a detail that signals you have written decorators rather than only read about them.
Generators, Iterators and Comprehensions
What is the difference between a list comprehension and a generator expression?
[x * x for x in range(1000000)] # builds the whole list in memory
(x * x for x in range(1000000)) # yields one at a time, constant memoryUse a generator when the sequence is large or you only need to iterate once.
What does yield do?
It turns a function into a generator. Calling it returns a generator object without running the body; each next() runs until the next yield and pauses there, keeping local state.
def countdown(n):
while n > 0:
yield n
n -= 1The payoff to state: constant memory regardless of sequence length, and the ability to represent infinite sequences.
What is an iterator?
An object with __iter__ and __next__ that raises StopIteration when exhausted. A for loop is syntax over this protocol. Every generator is an iterator; not every iterator is a generator.
What is the walrus operator?
:= assigns within an expression, which avoids computing something twice:
if (n := len(data)) > 10:
print(f'{n} items — too many')
OOP, Exceptions and the GIL
What is self?
A reference to the instance, passed automatically. It is a convention rather than a keyword, but never rename it.
Difference between a class method, static method and instance method?
An instance method takes self. A @classmethod takes cls and can construct instances — useful for alternative constructors. A @staticmethod takes neither and is simply a function grouped with the class.
What are dunder methods?
Special methods Python calls implicitly — __init__ for construction, __str__ for print, __len__ for len(), __eq__ for ==. Implementing them makes your class behave like a built-in.
What is the difference between __str__ and __repr__?
__str__ is for users, __repr__ for developers and debugging. If you implement only one, implement __repr__, since it is the fallback.
What is the GIL?
The Global Interpreter Lock allows only one thread to 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. For CPU-bound parallelism, use multiprocessing. This is a favourite question because many candidates have heard the term without being able to say what it implies.
try/except/else/finally?
else runs only if no exception occurred; finally always runs, and is where cleanup belongs. Catching bare except: is a bad habit — it swallows KeyboardInterrupt too.
