Python interview questions can test language fundamentals, data structures, functions, object-oriented programming, exception handling, iterators, generators, memory management, testing, and performance. This guide covers questions for freshers and experienced developers, with short explanations and runnable examples.
- Python fundamentals interview questions
- Python functions, arguments, and scope questions
- Python object-oriented programming questions
- Advanced Python interview questions
- Python interview preparation FAQs
Python Fundamentals Interview Questions for Freshers
What is Python and what are its key features?
Python is a high-level, general-purpose programming language designed around readable syntax. It supports procedural, object-oriented, and functional programming styles. Its main characteristics include dynamic typing, automatic memory management, an extensive standard library, an import-based module system, and implementations for several operating systems.
Is Python compiled or interpreted?
The answer depends on the Python implementation. CPython normally compiles source code into bytecode and then executes that bytecode in its virtual machine. Other implementations may use different compilation or execution strategies. It is therefore more accurate to describe Python as a language rather than classifying every implementation as purely compiled or purely interpreted.
How do you start the Python shell?
Open a terminal or command prompt and run python or python3, depending on the installation. This starts an interactive interpreter where statements can be entered at the >>> prompt. The version shown in the following existing example is illustrative; the installed version may differ.
$ python
Python 3.8.5 (default, Jul 28 2020, 12:59:40)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
What are Python’s built-in data types?
Common built-in Python data types include:
- Numeric types:
int,float, andcomplex - Sequence types:
list,tuple, andrange - Text type:
str - Mapping type:
dict - Set types:
setandfrozenset - Boolean type:
bool - Binary types:
bytes,bytearray, andmemoryview - Null-value type:
NoneType, whose sole instance isNone
Explain the difference between lists and tuples in Python.
Lists and tuples are ordered sequences. A list is mutable, so elements can be added, removed, or replaced after creation. A tuple is immutable. A tuple can be used as a dictionary key only when all the values needed for its hash are themselves hashable; immutability alone does not make every tuple hashable.
What is list slicing in Python?
Slicing selects part of a sequence with the syntax sequence[start:stop:step]. The start position is inclusive, the stop position is exclusive, and each component is optional. Negative indexes count from the end, while a negative step can traverse the sequence in reverse.
values = [10, 20, 30, 40, 50]
print(values[1:4]) # [20, 30, 40]
print(values[::2]) # [10, 30, 50]
print(values[::-1]) # [50, 40, 30, 20, 10]
What is list comprehension and how is it used in Python?
A list comprehension builds a list by evaluating an expression for items from an iterable, with an optional filtering condition. It is useful when the transformation remains short and readable. A regular loop is often clearer when the logic includes several operations or side effects.
# Traditional loop
squares = []
for x in range(10):
squares.append(x**2)
# List comprehension
squares = [x**2 for x in range(10)]
print(squares) # Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
What is the difference between append() and extend() in Python lists?
append() adds its argument as one new list element. extend() iterates over its argument and adds each item separately. Both methods mutate the list and return None.
my_list = [1, 2, 3]
my_list.append([4, 5])
print(my_list) # Output: [1, 2, 3, [4, 5]]
my_list = [1, 2, 3]
my_list.extend([4, 5])
print(my_list) # Output: [1, 2, 3, 4, 5]
How does Python’s set data type work?
A set is an unordered collection of unique, hashable elements. Sets are useful for membership tests, removing duplicates, and operations such as union, intersection, difference, and symmetric difference. Code should not depend on a set’s displayed or iteration order.
my_set = {1, 2, 3, 3}
print(my_set) # Output: {1, 2, 3}
my_set.add(4)
print(my_set) # Output: {1, 2, 3, 4}
another_set = {3, 4, 5}
print(my_set & another_set) # Output: {3, 4}
print(my_set | another_set) # Output: {1, 2, 3, 4, 5}
What is the difference between == and is in Python?
== tests value equality by invoking an equality operation. is tests object identity, meaning that both references point to the same object. Use is None when checking against None; do not use identity as a substitute for ordinary value comparison.
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # Output: True
print(a is b) # Output: False
print(a is c) # Output: True
What is the difference between break, continue, and pass?
break exits the nearest enclosing loop. continue skips the rest of the current loop iteration and proceeds to the next one. pass performs no operation and is used where Python syntax requires a statement.
for number in range(6):
if number == 1:
continue
if number == 4:
break
if number == 2:
pass
print(number)
0
2
3
What is the purpose of the pass statement in Python?
pass is a null statement. It is commonly used as a temporary body for a function, class, loop, or conditional branch. It should not be confused with continue, which changes loop control flow.
def my_function():
pass # TODO: implement this function later
class MyClass:
pass # Placeholder for future attributes and methods
How do you handle exceptions in Python?
Place operations that may fail in a try block and catch expected exception types in except blocks. The optional else block runs when no exception is raised, while finally runs during cleanup whether or not an exception occurred. Catch specific exceptions instead of suppressing every error indiscriminately.
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero.")
else:
print("Division successful.")
finally:
print("Execution completed.")
How do you handle multiple Python exceptions in one except block?
Specify a tuple of exception classes when the same recovery action is appropriate for each one. Use separate handlers when the exceptions require different messages or corrective actions.
try:
result = 10 / 0
except (ZeroDivisionError, TypeError) as e:
print(f"An error occurred: {e}")
What is the purpose of the assert statement?
assert checks an internal assumption and raises AssertionError when the condition is false. Assertions may be removed when Python runs with optimization, so they must not be used for input validation, authentication, authorization, or other required runtime checks.
def divide(a, b):
assert b != 0, "Denominator cannot be zero."
return a / b
print(divide(10, 2)) # Output: 5.0
# print(divide(10, 0)) # Raises AssertionError: Denominator cannot be zero.
What is PEP 8 and why is it useful?
PEP 8 is the style guide for Python code. It discusses naming, imports, whitespace, indentation, line layout, and related conventions. Teams may adopt automated formatting and linting rules that differ in details, but consistency within a codebase remains the practical objective.
Python Functions, Arguments, Modules, and Scope Interview Questions
What are Python decorators and how are they used?
A decorator receives a function or class and returns the object that will be bound to the decorated name. Decorators are used for concerns such as logging, caching, registration, authorization, instrumentation, and validation. Function decorators usually define a wrapper and should preserve useful metadata with functools.wraps.
@decorator
def function():
pass
What is a lambda function in Python?
A lambda expression creates a small anonymous function containing one expression. It can accept multiple parameters, but it cannot contain ordinary statements. A named function defined with def is usually clearer when the behavior is reused or needs documentation.
add = lambda x, y: x + y
print(add(2, 3)) # Output: 5
# Lambda function example
add = lambda x, y: x + y
print(add(2, 3)) # Output: 5
# Using lambda with map
squares = list(map(lambda x: x**2, range(5)))
print(squares) # Output: [0, 1, 4, 9, 16]
What do *args and **kwargs do in Python function definitions?
*args collects additional positional arguments into a tuple. **kwargs collects additional keyword arguments into a dictionary. The names args and kwargs are conventions; the * and ** syntax provides the behavior. Similar syntax can unpack iterables and mappings when calling a function.
def func(*args, **kwargs):
print("Arguments:", args)
print("Keyword Arguments:", kwargs)
func(1, 2, 3, name='Alice', age=30)
# Output:
# Arguments: (1, 2, 3)
# Keyword Arguments: {'name': 'Alice', 'age': 30}
What are Python modules and how do you use them?
A module is an importable unit of Python code, commonly stored in a .py file. Modules organize names and encourage reuse. Packages organize related modules. The import system loads a module and binds either the module or selected names in the importing namespace.
import math
result = math.sqrt(16)
print(result) # Output: 4.0
What is a namespace in Python?
A namespace maps names to objects. Python resolves ordinary names through local, enclosing, global, and built-in scopes, commonly summarized as LEGB. Not every namespace must be treated as a regular user-visible dictionary, even though mappings are central to many implementations.
# Example of namespaces
def foo():
x = 10 # Local namespace
print(x)
x = 20 # Global namespace
foo()
print(x)
What does the nonlocal keyword do?
nonlocal binds a name to an existing variable in the nearest enclosing function scope. It allows a nested function to rebind that variable. It does not refer to a global name, and the referenced binding must already exist in an enclosing non-global scope.
def outer():
count = 0
def inner():
nonlocal count
count += 1
print(count)
return inner
counter = outer()
counter() # Output: 1
counter() # Output: 2
What are type hints in Python?
Type hints annotate expected types for parameters, return values, variables, and other constructs. Python does not enforce most annotations automatically at runtime. Static analysis tools, editors, documentation generators, frameworks, and application code can inspect and use them.
def greet(name: str) -> str:
return f"Hello, {name}!"
def add(a: int, b: int) -> int:
return a + b
# Using type hints with variables
age: int = 30
name: str = "Alice"
What are docstrings in Python?
A docstring is a string literal placed first in a module, class, function, or method body. It documents the object’s purpose and interface and is normally available through __doc__ and help(). Documentation tools can also extract it.
def greet(name):
"""
Greets the person with the given name.
Parameters:
name (str): The name of the person.
Returns:
None
"""
print(f"Hello, {name}!")
print(greet.__doc__)
How do you format strings in Python?
Python supports percent-style formatting, str.format(), and formatted string literals called f-strings. F-strings are concise when expressions are already available as trusted program values. SQL statements and shell commands should use their own parameterization mechanisms rather than being assembled from untrusted values with string formatting.
# Old-style formatting
name = "Alice"
age = 30
print("Hello, %s. You are %d years old." % (name, age))
# str.format()
print("Hello, {}. You are {} years old.".format(name, age))
# f-strings
print(f"Hello, {name}. You are {age} years old.")
Python Object-Oriented Programming Interview Questions
What is the purpose of self in Python classes?
self conventionally names the instance received by an instance method. It gives the method access to instance attributes and other methods. It is not a reserved keyword, but using the established name makes code easier to recognize.
class MyClass:
def __init__(self, value):
self.value = value # 'self.value' refers to the instance variable
def display(self):
print(self.value)
obj = MyClass(10)
obj.display() # Output: 10
What is the purpose of __init__() in a Python class?
__init__() initializes an instance after it has been created. Object creation itself is handled earlier, normally through __new__(). Calling __init__() a constructor is common shorthand, but initializer is the more precise term.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 30)
print(p.name) # Output: Alice
print(p.age) # Output: 30
How does inheritance work in Python?
A subclass can inherit attributes and behavior from one or more base classes. It may add methods or override inherited methods. Python uses its method resolution order to determine where an attribute is found, which is especially relevant in multiple inheritance. super() supports cooperative method calls along that order.
class Animal:
def speak(self):
print("Animal speaks")
class Dog(Animal):
def speak(self):
print("Dog barks")
dog = Dog()
dog.speak() # Output: Dog barks
What is the difference between __str__() and __repr__()?
__str__() supplies a readable representation for users. __repr__() supplies a representation intended for developers and debugging; when practical, it should be unambiguous. If a class does not define __str__(), Python falls back to __repr__().
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Person('{self.name}', {self.age})"
def __str__(self):
return f"{self.name}, {self.age} years old"
p = Person("Alice", 30)
print(repr(p)) # Output: Person('Alice', 30)
print(str(p)) # Output: Alice, 30 years old
How is the property decorator used in Python?
@property exposes method-controlled behavior through attribute syntax. A getter can compute or retrieve a value, and an optional setter can validate assignments. This allows an implementation to change without forcing callers to switch immediately from attribute access to explicit getter methods.
class Celsius:
def __init__(self, temperature=0):
self._temperature = temperature
@property
def temperature(self):
"""Get the temperature"""
return self._temperature
@temperature.setter
def temperature(self, value):
"""Set the temperature with validation"""
if value < -273.15:
raise ValueError("Temperature below -273.15 is not possible")
self._temperature = value
c = Celsius()
c.temperature = 25
print(c.temperature) # Output: 25
# c.temperature = -300 # Raises ValueError
class Celsius:
def __init__(self, temperature=0):
self._temperature = temperature
@property
def temperature(self):
"""Get the temperature"""
return self._temperature
@temperature.setter
def temperature(self, value):
"""Set the temperature with validation"""
if value < -273.15:
raise ValueError("Temperature below -273.15 is not possible")
self._temperature = value
c = Celsius()
c.temperature = 25
print(c.temperature) # Output: 25
# c.temperature = -300 # Raises ValueError
What is the difference between staticmethod and classmethod?
A static method receives no automatic instance or class argument and behaves like a function placed in the class namespace. A class method receives the current class as its first argument, conventionally named cls. Class methods are often used for alternative constructors because subclass calls receive the subclass rather than a fixed base class.
class MyClass:
@staticmethod
def static_method():
print("This is a static method.")
@classmethod
def class_method(cls):
print(f"This is a class method of {cls}.")
MyClass.static_method() # Output: This is a static method.
MyClass.class_method() # Output: This is a class method of <class '__main__.MyClass'>.
Advanced Python Interview Questions for Experienced Developers
How does Python handle memory management?
Memory behavior is implementation-specific. CPython stores objects in a managed private heap, primarily uses reference counting to reclaim many unreachable objects promptly, and supplements it with a cyclic garbage collector. Its allocators may keep released memory for later Python allocations rather than immediately returning it to the operating system.
How does Python’s garbage collection work?
In CPython, reference counting handles many objects, while the cyclic garbage collector detects unreachable reference cycles. Other Python implementations may use different garbage-collection strategies. Resource cleanup should not depend solely on garbage-collection timing; files, locks, transactions, and connections should be managed explicitly, commonly with context managers.
What is the difference between shallow copy and deep copy?
A shallow copy creates a new outer object but reuses references to nested objects. A deep copy recursively copies supported nested objects and tracks objects already copied so that recursive structures can be handled. A deep copy is not always desirable: some resources should remain shared or cannot be meaningfully duplicated.
import copy
original = [[1, 2], [3, 4]]
shallow = copy.copy(original)
deep = copy.deepcopy(original)
original[0][0] = 'changed'
print(shallow) # [['changed', 2], [3, 4]]
print(deep) # [[1, 2], [3, 4]]
import copy
original = [[1, 2], [3, 4]]
shallow = copy.copy(original)
deep = copy.deepcopy(original)
original[0][0] = 'changed'
print(shallow) # Output: [['changed', 2], [3, 4]]
print(deep) # Output: [[1, 2], [3, 4]]
What is the Global Interpreter Lock in Python?
The Global Interpreter Lock is an implementation detail associated especially with traditional GIL-enabled CPython builds. It limits simultaneous execution of Python bytecode by multiple threads in one interpreter, although threads can still overlap I/O and native code may release the lock. Processes are a common option for CPU-bound parallelism. Answers should avoid claiming that the GIL itself prevents all race conditions; shared mutable state still requires synchronization. Python implementation and build details can affect this behavior.
What are generators in Python and how do they work?
A generator produces values lazily and preserves its execution state between yields. Calling a generator function returns a generator object without immediately running the body. Iteration resumes execution until yield produces a value; completion raises StopIteration internally to end iteration.
def countdown(n):
while n > 0:
yield n
n -= 1
# Using the generator
for number in countdown(5):
print(number)
# Output:
# 5
# 4
# 3
# 2
# 1
What does yield from do in Python?
yield from delegates part of a generator’s operation to another iterable. Beyond yielding its values, it forwards generator protocol operations and captures the delegated generator’s return value. It is useful for composing generators without writing a manual forwarding loop.
def generator1():
yield from range(3)
def generator2():
yield from generator1()
yield from ['a', 'b']
for value in generator2():
print(value)
# Output:
# 0
# 1
# 2
# a
# b
What are context managers in Python?
A context manager defines setup and cleanup behavior around a with block. Class-based context managers implement __enter__() and __exit__(). Generator-based context managers can be created with contextlib.contextmanager. They are commonly used for files, locks, database transactions, and temporary state.
from contextlib import contextmanager
@contextmanager
def open_file(name, mode):
f = open(name, mode)
try:
yield f
finally:
f.close()
with open_file('test.txt', 'w') as f:
f.write('Hello, World!')
How does Python’s with statement work?
The with statement enters a context manager before executing its body and exits it afterward. The exit operation runs even when the block raises an exception. The context manager may suppress an exception deliberately, although most resource managers perform cleanup and allow the exception to propagate.
with open('example.txt', 'r') as file:
content = file.read()
print(content)
# The file is automatically closed after the block
How do you handle file operations in Python?
Use open() with an appropriate text or binary mode. A with statement ensures that the file is closed after the block. Specify an encoding when text must be read or written consistently across environments, and handle expected exceptions such as missing files or permission errors.
# Reading a file
with open('example.txt', 'r') as file:
content = file.read()
print(content)
# Writing to a file
with open('example.txt', 'w') as file:
file.write('Hello, World!')
What is monkey patching in Python?
Monkey patching replaces or adds attributes on a class, module, or object at runtime. It is sometimes used in tests or compatibility layers, but it creates hidden global effects and can depend on implementation details. Dependency injection or a narrowly scoped test patch is usually easier to maintain.
import some_module
def new_function():
print("This is a monkey patched function.")
some_module.original_function = new_function
some_module.original_function() # Output: This is a monkey patched function.
How do you create and activate a Python virtual environment?
The standard venv module creates an isolated environment with its own interpreter-facing commands and package installation location. Activation adjusts the current shell environment; it is convenient but not required when the environment’s interpreter is invoked directly.
$ python -m venv myenv
$ source myenv/bin/activate # On Unix or MacOS
myenv\Scripts\activate # On Windows
How do you perform unit testing in Python?
Python includes the unittest framework, while projects may also use third-party test runners. A useful unit test checks one behavior, supplies controlled inputs, and verifies an observable result. Tests should cover normal cases, boundaries, expected failures, and cleanup where relevant.
import unittest
def add(a, b):
return a + b
class TestAddFunction(unittest.TestCase):
def test_add_positive(self):
self.assertEqual(add(2, 3), 5)
def test_add_negative(self):
self.assertEqual(add(-1, -1), -2)
if __name__ == '__main__':
unittest.main()
How can you optimize Python code for performance?
Measure before optimizing. Use representative workloads and a profiler to determine whether time is spent in Python code, database queries, network calls, serialization, memory allocation, or another dependency. After locating the bottleneck, possible changes include selecting a better algorithm or data structure, reducing repeated work, batching I/O, caching with a clear invalidation policy, using optimized libraries, or choosing processes, native extensions, or another runtime for suitable CPU-bound work. List comprehensions and __slots__ are not automatic performance solutions and should be selected only after measurement.
Python Interview Preparation FAQs
What basic Python interview questions should freshers prepare?
Freshers should prepare Python data types, mutability, slicing, dictionaries and sets, loops, functions, *args and **kwargs, exceptions, modules, classes, comprehensions, iterators, generators, and virtual environments. They should also be able to trace a short program and explain its output.
Which Python questions are common for experienced developers?
Experienced interviews often cover descriptors and properties, decorators, context managers, generators, concurrency, the GIL, memory behavior, packaging, type checking, testing strategy, profiling, database access, API design, and production debugging. The exact emphasis depends on whether the role involves web development, automation, data analysis, or another domain.
Do Python data analyst interviews include coding questions?
They may include Python collection operations, missing-value handling, grouping, joins, transformations, date processing, and interpretation of tabular results. SQL, statistics, data validation, and clear explanation of assumptions may also be assessed, depending on the role.
Should Python interview answers mention the implementation?
Yes, when behavior depends on it. Statements about reference counting, the GIL, object caching, memory allocation, or bytecode often describe CPython rather than every Python implementation. Naming that scope makes the answer more precise.
How should candidates prepare for Python coding interview problems?
Practise explaining the approach before coding, selecting suitable data structures, stating time and space complexity, handling empty and invalid inputs, and testing boundary cases. Review lists, dictionaries, sets, stacks, queues, sorting, searching, string processing, recursion, iteration, and common graph or tree patterns when relevant to the role.
Python Interview Questions Editorial QA Checklist
- Confirm that statements about the GIL, reference counting, and bytecode identify CPython-specific behavior where necessary.
- Verify that
isis used for identity and==for value equality. - Check that slicing examples explain the exclusive stop index and optional step.
- Ensure
break,continue, andpassare described as distinct control-flow operations. - Confirm that tuple hashability is not claimed when a tuple contains unhashable elements.
- Check that assertions are not recommended for user-input validation or security controls.
- Run Python examples after HTML entities are decoded and verify that displayed output does not rely on unordered set formatting.
- Review performance advice for measurement, algorithm choice, and workload context rather than unsupported micro-optimizations.
TutorialKart.com