0% found this document useful (0 votes)
3 views13 pages

Python Interview Questions Answers

This document provides a comprehensive list of Python interview questions and answers, covering various topics such as data types, memory management, string manipulation, collections, functions, and object-oriented programming. It includes explanations of key concepts, differences between similar features, and practical examples. The content is designed to help candidates prepare for Python-related interviews by understanding essential concepts and common questions.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views13 pages

Python Interview Questions Answers

This document provides a comprehensive list of Python interview questions and answers, covering various topics such as data types, memory management, string manipulation, collections, functions, and object-oriented programming. It includes explanations of key concepts, differences between similar features, and practical examples. The content is designed to help candidates prepare for Python-related interviews by understanding essential concepts and common questions.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Python Interview Prep

Python Interview Questions & Answers


100 Core Python Questions (No External Libraries) — Interview-Ready Answers

Basics & Data Types


Q1. What is the difference between a list and a tuple?
Lists are mutable, ordered collections defined with square brackets; tuples are immutable, ordered
collections defined with parentheses. Because tuples are immutable, they're hashable (can be used as dict
keys) and are generally faster to create and iterate over than lists.

Q2. What are Python's built-in data types?


Numeric types (int, float, complex), sequence types (str, list, tuple, range), mapping type (dict), set types
(set, frozenset), boolean (bool), and NoneType. Each has specific mutability and ordering characteristics.

Q3. How is memory managed in Python?


Python uses a private heap managed by the interpreter. Objects are allocated on this heap, and memory is
reclaimed automatically through reference counting combined with a cyclic garbage collector that detects
and cleans up reference cycles.

Q4. What is the difference between 'is' and '=='?


'==' checks value equality (do two objects contain the same data), while 'is' checks identity (do two
references point to the same object in memory). Two equal objects aren't necessarily the same object.

Q5. What are mutable and immutable types in Python? Give examples.
Mutable objects can be changed after creation (list, dict, set); immutable objects cannot (int, float, str,
tuple, frozenset). This matters for default arguments, hashability, and how objects behave when passed to
functions.

Q6. How does Python handle integer overflow?


Python's int type has arbitrary precision, so it automatically grows to accommodate large values — there's
no fixed-size overflow like in C. The only real limit is available memory.

Q7. What is the difference between int and float division using '/' and '//'?
'/' always performs true division and returns a float, e.g. 7/2 = 3.5. '//' performs floor division, rounding
down to the nearest whole number, e.g. 7//2 = 3, and -7//2 = -4.

Q8. What is the output of 0.1 + 0.2 == 0.3? Why?


It's False. Floating-point numbers are stored in binary IEEE-754 format, which can't represent decimals
like 0.1 exactly, causing tiny rounding errors. The correct way to compare is using [Link]() or
checking the difference is below a small tolerance.

Page 1
Python Interview Prep

Q9. What is the difference between None, False, and 0?


None represents the absence of a value (Python's null); False is the boolean value representing falsehood;
0 is the integer zero. All three are 'falsy' in a boolean context, but they are distinct objects of different
types.

Q10. How do you swap two variables without a temporary variable?


Using tuple unpacking: a, b = b, a. Python evaluates the right-hand side as a tuple first, then unpacks it
into the variables, so no temporary variable is needed.

Q11. What is the difference between str and bytes?


str represents Unicode text (sequence of characters), while bytes represents raw binary data (sequence of
integers 0-255). You convert between them using .encode() (str to bytes) and .decode() (bytes to str).

Q12. What is type coercion vs type casting?


Type coercion is implicit conversion done automatically by Python, e.g. 1 + 2.0 becomes 3.0. Type
casting is explicit conversion done by the programmer using functions like int(), str(), or float().

Q13. How do you check the type of a variable?


Use type(variable) to get the exact type, or isinstance(variable, SomeType) to check if it's an instance of a
type or its subclasses — isinstance() is generally preferred because it respects inheritance.

Q14. What is the difference between shallow copy and deep copy?
A shallow copy ([Link]() or [Link]()) creates a new outer object but keeps references to the same
nested objects. A deep copy ([Link]()) recursively copies all nested objects, so the two structures
are fully independent.

Q15. What is the id() function used for?


id() returns the unique integer identifier of an object, which in CPython corresponds to its memory
address. It's used to check whether two variables refer to the exact same object, often alongside the 'is'
operator.

Page 2
Python Interview Prep

Strings
Q16. How do you reverse a string in Python?
The most idiomatic way is slicing: s[::-1]. This creates a new string by stepping through the original in
reverse order.

Q17. What is string interning?


String interning is an optimization where Python reuses memory for identical short, immutable strings
(like variable names or literals) instead of creating duplicates. This is why short identical strings often
satisfy 'is' comparisons as well as '=='.

Q18. What's the difference between .format() and f-strings?


Both format strings, but f-strings (f'{value}') are evaluated at runtime, are more concise, and are generally
faster because the expressions are compiled directly into the string. .format() is more verbose but works
well when the template is built dynamically.

Q19. How do you check if a string is a palindrome?


Compare the string to its reverse: s == s[::-1]. For case/space-insensitive checks, first normalize with
[Link]().replace(' ', '').

Q20. What's the difference between split() and rsplit()?


split() splits from the left and rsplit() splits from the right; by default (no maxsplit) they produce the same
result, but with a maxsplit limit they differ — rsplit() keeps the rightmost splits intact.

Q21. How do you remove whitespace from a string?


Use .strip() to remove leading/trailing whitespace, .lstrip()/.rstrip() for one side only, and .replace(' ', '') or
a regex if you need to remove all whitespace including internal spaces.

Q22. What is the difference between find() and index()?


Both search for a substring and return its position. find() returns -1 if the substring isn't found, while
index() raises a ValueError. find() is safer when the substring's presence isn't guaranteed.

Q23. How do you check if a string contains only digits?


Use the string method .isdigit() (or .isnumeric()/.isdecimal() depending on the exact character set you
want to allow).

Q24. How would you count the frequency of each character in a string?
Iterate through the string and build a dictionary incrementing counts, e.g. {} then for ch in s: counts[ch] =
[Link](ch, 0) + 1. ([Link] does this too, but that's a library.)

Q25. What does [Link]() do and why is it preferred over '+' for concatenation?
join() concatenates an iterable of strings using a separator, e.g. ','.join(['a','b']) → 'a,b'. It's preferred over
repeated '+' in a loop because strings are immutable, so '+' concatenation creates a new string each time
(O(n²) overall), while join() builds the result in one efficient pass.

Page 3
Python Interview Prep

Lists, Tuples, Sets, Dicts


Q26. What is the difference between append() and extend()?
append() adds a single element to the end of a list, even if that element is itself a list (it becomes one
nested item). extend() takes an iterable and adds each of its elements individually to the list.

Q27. How do you remove duplicates from a list?


Convert it to a set and back to a list: list(set(my_list)). Note this doesn't preserve order; to preserve order,
use [Link](my_list) or a manual loop with a 'seen' set.

Q28. What is list comprehension? Give an example.


A concise syntax for creating a list from an iterable in a single line, optionally with a condition. Example:
squares = [x**2 for x in range(10) if x % 2 == 0].

Q29. What is the difference between a list and a set?


A list is ordered, allows duplicates, and is indexable. A set is unordered, stores only unique elements, and
offers O(1) average membership testing versus O(n) for a list.

Q30. How do dictionaries maintain order in modern Python?


Since Python 3.7, dictionaries maintain insertion order as a language guarantee (it was a CPython
implementation detail in 3.6). Iterating over a dict yields keys in the order they were added.

Q31. What is a dictionary comprehension?


A concise way to build a dict from an iterable: {k: v for k, v in pairs}. Example: {x: x**2 for x in
range(5)}.

Q32. How do you merge two dictionaries?


In Python 3.9+, use the merge operator: merged = d1 | d2. Before that, use {**d1, **d2} or
[Link](d2). In all cases, keys in the second dict overwrite matching keys from the first.

Q33. What's the time complexity of accessing an element in a list vs a dict?


List access by index is O(1), but searching by value is O(n). Dict access by key is O(1) average case
(based on hashing), though worst case is O(n) with many hash collisions.

Q34. Why are tuples faster than lists?


Tuples are immutable, so Python can allocate a fixed, exact-sized block of memory and doesn't need the
extra overhead lists carry for resizing/mutation. Tuples also allow certain internal optimizations like
caching for constant tuples.

Q35. How do you sort a list of dictionaries by a specific key?


Use sorted() with a key function: sorted(data, key=lambda d: d['age']). Add reverse=True for descending
order.

Q36. What is the difference between sort() and sorted()?


[Link]() sorts the list in place and returns None; sorted() returns a new sorted list and leaves the original
unchanged, and it works on any iterable, not just lists.

Page 4
Python Interview Prep

Q37. How do you flatten a nested list?


A simple approach for one level of nesting is a list comprehension: [item for sublist in nested for item in
sublist]. For arbitrary depth, use a recursive function.

Q38. What is a namedtuple and why might you use it?


It's a tuple subclass with named fields, letting you access elements by name (p.x) instead of only by index
(p[0]), while still being immutable and lightweight — useful for readable, structured data without
defining a full class.

Q39. How does Python implement sets internally?


Sets are implemented using a hash table, similar to dictionaries but storing only keys (no values). This
gives average O(1) time for add, remove, and membership testing.

Q40. What happens if you use a mutable object as a dictionary key?


It raises a TypeError, because dictionary keys must be hashable, and mutable objects like lists don't
implement __hash__ (since their contents, and thus their hash, could change).

Q41. How do you find the intersection and union of two sets?
Use a & b or [Link](b) for the common elements, and a | b or [Link](b) for all elements from both
sets.

Q42. What's the difference between pop() and remove() on a list?


pop(index) removes and returns the element at a given index (default last), and raises IndexError if out of
range. remove(value) removes the first matching value, and raises ValueError if the value isn't found.

Q43. How do you iterate over a dictionary's keys and values simultaneously?
Use the .items() method: for key, value in my_dict.items(): ...

Q44. What is the difference between [Link]() and [Link]()?


[Link]() performs a shallow copy — a new list with references to the same nested objects. deepcopy()
recursively duplicates every nested object so the copy is fully independent of the original.

Q45. How would you implement a stack and a queue using Python lists?
A stack can use a list with append()/pop() (both O(1) at the end). A queue is better implemented with
[Link] since [Link](0) is O(n); with a plain list you'd simulate it with insert(0, x) and pop(0),
though that's inefficient for large data.

Page 5
Python Interview Prep

Functions
Q46. What is the difference between *args and **kwargs?
*args collects any number of extra positional arguments into a tuple; **kwargs collects extra keyword
arguments into a dictionary. They let a function accept a flexible, variable number of arguments.

Q47. What are default arguments, and why can mutable defaults be dangerous?
Default arguments provide a fallback value if the caller doesn't supply one. Mutable defaults (like a list)
are dangerous because the default object is created once at function definition time and shared across all
calls, so mutations persist between calls — the standard fix is to default to None and create the mutable
object inside the function.

Q48. What is a lambda function? When would you use one?


A lambda is a small, anonymous, single-expression function defined with the lambda keyword, e.g.
lambda x: x * 2. It's useful for short, throwaway functions, often as an argument to sorted() or map(),
where defining a full function would be overkill.

Q49. What is the difference between a function and a method?


A function is a standalone block of reusable code. A method is a function defined inside a class and
bound to instances (or the class itself), implicitly receiving self (or cls) as its first argument.

Q50. What are '*' and '/' in function signatures used for?
'*' in a signature marks all following parameters as keyword-only (must be passed by name). '/' marks all
preceding parameters as positional-only (cannot be passed by name). They give precise control over how
a function's API can be called.

Q51. What is recursion? Write a recursive function to compute factorial.


Recursion is when a function calls itself to solve smaller instances of a problem until reaching a base
case. Example:
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)

Q52. What is a closure? Give an example.


A closure is a nested function that captures and remembers variables from its enclosing scope even after
that outer function has finished executing. Example:
def make_multiplier(n):
def multiplier(x):
return x * n
return multiplier
times3 = make_multiplier(3)
times3(5) # 15

Page 6
Python Interview Prep

Q53. What is the difference between return and yield?


return exits a function immediately and sends back a single value, ending execution. yield pauses the
function, returns a value, and preserves its state so execution can resume from that point on the next call
— this is what turns a function into a generator.

Q54. What is function overloading, and does Python support it natively?


Function overloading means defining multiple functions with the same name but different parameters.
Python doesn't support this natively — a later definition simply overwrites an earlier one — but similar
behavior can be achieved with default arguments, *args/**kwargs, or manual type checks.

Q55. How do you pass a function as an argument to another function?


Functions are first-class objects in Python, so you simply pass the function name (without calling it) as an
argument, e.g. sorted(data, key=my_function).

Q56. What is a higher-order function?


A function that either takes one or more functions as arguments, returns a function, or both. Examples
include map(), filter(), and any function that returns a closure.

Q57. What is the difference between pass-by-value and pass-by-reference, and


how does Python handle argument passing?
Pass-by-value copies the value; pass-by-reference passes a reference to the original variable, so changes
affect the caller's variable. Python uses 'pass-by-object-reference': the reference to the object is passed, so
mutable objects can be modified in place, but reassigning the parameter inside the function doesn't affect
the caller's variable.

Q58. What does the global keyword do?


It tells Python that an assignment inside a function should modify a variable in the module's global scope
rather than creating a new local variable.

Q59. What does the nonlocal keyword do?


It's used inside a nested function to indicate that a variable refers to one in the nearest enclosing (non-
global) scope, allowing that outer variable to be reassigned rather than shadowed.

Q60. How can you enforce type hints, and are they enforced at runtime?
Type hints (e.g. def f(x: int) -> str) are not enforced by the Python interpreter at runtime — they're purely
documentation/IDE hints unless you use a separate static type checker (like mypy) or add manual runtime
checks yourself.

Page 7
Python Interview Prep

Object-Oriented Programming
Q61. What is the difference between a class method, static method, and instance
method?
An instance method takes self and can access/modify instance state. A class method takes cls (via
@classmethod) and operates on the class itself, often used for alternative constructors. A static method
(@staticmethod) takes neither self nor cls — it's just a regular function logically grouped inside the class.

Q62. What is self and why is it required?


self refers to the specific instance a method is being called on, letting the method access and modify that
instance's attributes. It's explicitly required as the first parameter because Python doesn't implicitly pass
the instance the way some other languages do.

Q63. What is inheritance? Give an example of single and multiple inheritance.


Inheritance lets a class acquire attributes and methods from another class. Single inheritance: class
Dog(Animal). Multiple inheritance: class Duck(Swimmer, Flyer) — Duck inherits from both Swimmer
and Flyer.

Q64. What is method resolution order (MRO)?


MRO is the order in which Python searches parent classes for a method or attribute when using
inheritance, especially multiple inheritance. Python uses the C3 linearization algorithm, viewable via
ClassName.__mro__ or [Link]().

Q65. What is polymorphism in Python? Give an example.


Polymorphism allows different classes to be treated through a common interface, where the same method
name behaves differently depending on the object's actual class. Example: both Dog and Cat classes
implement a speak() method, and calling [Link]() works correctly regardless of the object's specific
type.

Q66. What is encapsulation, and how is it achieved in Python?


Encapsulation is bundling data and the methods that operate on it, while restricting direct access to
internal state. Python achieves this by convention: a single underscore (_attr) signals 'protected' (internal
use), and a double underscore (__attr) triggers name mangling to make it harder to access from outside —
there's no true enforced private access.

Q67. What are dunder (magic) methods? Name a few and their purposes.
Dunder ('double underscore') methods let objects integrate with Python's built-in syntax. Examples:
__init__ (constructor), __str__ (informal string representation), __len__ (support for len()), __eq__
(equality comparison), __add__ (support for the + operator).

Q68. What is the difference between __str__ and __repr__?


__str__ returns a readable, user-friendly string representation (used by print() and str()). __repr__ returns
an unambiguous, developer-facing representation, ideally one that could recreate the object; it's used by
the interpreter and as a fallback if __str__ isn't defined.

Page 8
Python Interview Prep

Q69. What is a property decorator (@property) used for?


It lets a method be accessed like an attribute (without parentheses), enabling controlled access to internal
data — e.g. computing a value on the fly or validating input on assignment via a paired @[Link] —
while keeping a clean, attribute-style API.

Q70. What is the difference between composition and inheritance?


Inheritance models an 'is-a' relationship, where a subclass extends a parent class. Composition models a
'has-a' relationship, where a class contains instances of other classes as attributes to reuse functionality.
Composition is often favored for flexibility and looser coupling.

Q71. What is an abstract class, and how do you create one in Python?
An abstract class defines a common interface but cannot be instantiated directly, forcing subclasses to
implement certain methods. In Python, you create one by inheriting from ABC (from the abc module) and
marking methods with @abstractmethod.

Q72. What is duck typing?


A concept where an object's suitability is determined by whether it has the needed methods/attributes, not
by its explicit type — 'if it walks like a duck and quacks like a duck, it's a duck.' This is central to how
Python handles polymorphism without requiring explicit interfaces.

Q73. What is the diamond problem, and how does Python resolve it?
It occurs in multiple inheritance when two parent classes both inherit from a common base class, creating
ambiguity about which parent's version of a method/attribute should be used. Python resolves it using the
C3 linearization algorithm to compute a consistent, predictable MRO.

Q74. What is operator overloading? Give an example using __add__.


Operator overloading lets custom objects respond to built-in operators by defining special dunder
methods. Example: defining __add__(self, other) in a Vector class allows two Vector instances to be
combined using the + operator.

Q75. What is the difference between class variables and instance variables?
Class variables are shared across all instances of a class (defined directly in the class body) and are the
same for every object unless overridden. Instance variables are unique to each object, typically defined
inside __init__ using self.

Page 9
Python Interview Prep

Exceptions & Error Handling


Q76. What is the difference between Exception and BaseException?
BaseException is the root of the exception hierarchy and includes system-exiting exceptions like
SystemExit and KeyboardInterrupt. Exception is a subclass of BaseException and is the base for almost
all exceptions you should actually catch in normal code — catching Exception avoids accidentally
intercepting system-level signals.

Q77. How does try/except/else/finally work?


Code in try runs first; if an exception occurs, matching except blocks handle it. The else block runs only if
no exception occurred. The finally block always runs regardless of whether an exception occurred,
typically used for cleanup like closing files.

Q78. How do you create a custom exception?


Define a class that inherits from Exception (or a more specific built-in exception): class
MyError(Exception): pass. You can then raise it with raise MyError('message') and optionally add custom
attributes via __init__.

Q79. What happens if an exception occurs inside a finally block?


If a new exception is raised inside finally, it propagates and effectively replaces/suppresses any exception
that was being handled — the original exception's context is lost unless deliberately preserved.

Q80. What is the difference between raise and raise from?


raise simply raises an exception. raise NewError() from original_error explicitly chains the new exception
to the original one, preserving the causal relationship in the traceback so it's clear the new error stemmed
from handling the original.

Q81. What is exception chaining?


When an exception is raised while handling another exception, Python automatically links them, showing
'During handling of the above exception, another exception occurred' in the traceback — this preserves
the full context of what went wrong, and can also be done explicitly with 'raise ... from ...'.

Q82. How do you catch multiple exceptions in one block?


Use a tuple of exception types in a single except clause: except (ValueError, TypeError) as e: ... This runs
the same handling code for any of the listed exception types.

Page 10
Python Interview Prep

Iterators, Generators & Decorators


Q83. What is the difference between an iterable and an iterator?
An iterable is any object that can return an iterator (implements __iter__), such as a list or string. An
iterator is the object that actually produces values one at a time (implements both __iter__ and __next__)
and maintains state about where it is in the sequence.

Q84. How do you create a custom iterator using __iter__ and __next__?
Define a class with __iter__(self) returning self, and __next__(self) returning the next value or raising
StopIteration when exhausted. This lets instances be used directly in for loops.

Q85. What is a generator, and how does it differ from a normal function?
A generator is a function containing yield that produces a sequence of values lazily, one at a time, pausing
its state between each call instead of computing and returning everything at once like a normal function
does with return.

Q86. What is the purpose of the yield keyword?


yield pauses a function's execution and returns a value to the caller, while preserving all local state so
execution can resume exactly where it left off on the next call — this is what makes a function a
generator, enabling memory-efficient iteration over potentially large or infinite sequences.

Q87. What is a generator expression vs a list comprehension?


A list comprehension ([x for x in range(10)]) builds the entire list in memory immediately. A generator
expression ((x for x in range(10)), using parentheses) produces values lazily, one at a time, which is more
memory-efficient for large datasets.

Q88. What is a decorator? Write a simple example.


A decorator is a function that wraps another function to extend or modify its behavior without changing
its source code, applied using the @decorator syntax. Example:
def my_decorator(func):
def wrapper(*args, **kwargs):
print('Before call')
result = func(*args, **kwargs)
print('After call')
return result
return wrapper

@my_decorator
def greet():
print('Hello')

Q89. How do you write a decorator that accepts arguments?


Add an extra outer function that takes the decorator's arguments and returns the actual decorator.
Example:
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):

Page 11
Python Interview Prep

for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator

@repeat(3)
def greet():
print('Hi')

Q90. What is the difference between @staticmethod and a decorator you define
yourself?
@staticmethod is a built-in decorator that simply removes the implicit self/cls binding from a method. A
custom decorator is user-defined and can add arbitrary behavior — logging, timing, caching, validation
— around a function's execution.

Q91. What does [Link] do (conceptually)?


When you write a decorator, the wrapper function normally replaces the original function's name,
docstring, and metadata. wraps() copies that metadata from the original function onto the wrapper, so
introspection tools and debugging still show the original function's identity.

Q92. What is lazy evaluation, and how do generators support it?


Lazy evaluation means computing values only when they're actually needed, rather than all upfront.
Generators support this naturally because each value is produced on demand via yield, so you can work
with very large or even infinite sequences without holding them all in memory at once.

Page 12
Python Interview Prep

Memory, Performance & Internals


Q93. What is the Global Interpreter Lock (GIL), and how does it affect
multithreading?
The GIL is a mutex in CPython that allows only one thread to execute Python bytecode at a time, even on
multi-core systems. This means CPU-bound multithreaded programs don't get true parallelism, though
I/O-bound programs can still benefit from threading since the GIL is released during I/O waits.

Q94. What is garbage collection in Python, and how does reference counting
work?
Every object keeps a count of references pointing to it; when that count drops to zero, the memory is
immediately freed. This handles most cases, but reference cycles (objects referencing each other) aren't
caught by counting alone, so Python also runs a separate cyclic garbage collector to detect and clean those
up.

Q95. What causes a RecursionError, and what is the recursion limit?


Python limits the depth of the call stack (default around 1000 frames) to prevent a stack overflow from
runaway recursion. Exceeding this raises a RecursionError; the limit can be inspected/changed with
[Link]() and [Link](), though raising it too high risks crashing the interpreter.

Q96. What are Python's namespaces and scope resolution (LEGB rule)?
A namespace maps names to objects. When resolving a name, Python searches in order: Local (current
function), Enclosing (any outer function), Global (module level), and Built-in (Python's built-in names)
— this is the LEGB rule.

Q97. What is monkey patching?


Monkey patching means dynamically modifying or extending a class or module at runtime — e.g.
reassigning a method on an existing class — without altering its original source code. It's powerful for
testing or quick fixes but can make code harder to understand and maintain.

Q98. What is the difference between compiled and interpreted execution in


Python?
Python source code is first compiled to platform-independent bytecode (.pyc), which is then executed by
the Python Virtual Machine (PVM), an interpreter. So Python is technically both compiled and
interpreted — it isn't compiled directly to native machine code like C.

Q99. What is the difference between __init__ and __new__?


__new__ is a static method responsible for actually creating and returning a new instance (allocating
memory); it runs first. __init__ then initializes that already-created instance's attributes. __new__ is rarely
overridden except when subclassing immutable types or implementing patterns like singletons.

Q100. What are context managers, and how does the with statement work under
the hood?
A context manager handles setup and teardown logic around a block of code, most commonly for
resource management (like files). It's implemented via __enter__ (called when entering the with block,
returning the resource) and __exit__ (called on exit, even if an exception occurred, typically used to
release the resource).

Page 13

You might also like