Beginner Level (0–1 Years)
1. What is the output of bool("False")
in Python?
Answer:
It returns True
because any non-empty string is truthy, even the string "False"
.
2. Explain the difference between is
and ==
in Python.
Answer:
==
checks for value equality, while is
checks for identity (same memory location).
3. How do you create a list of squares of numbers from 1 to 5 using a list comprehension?
Answer:
Use [x**2 for x in range(1, 6)]
, which returns [1, 4, 9, 16, 25]
. The list comprehension iterates over the range and computes each number’s square.
4. Why does 0.1 + 0.2 == 0.3
return False
in Python?
Answer:
Due to floating-point precision errors, 0.1 + 0.2
is actually 0.30000000000000004
, which is not exactly equal to 0.3
.
5. What does the pass
statement do?
Answer:
It does nothing; it’s a placeholder used when a statement is syntactically required but no action is needed.
6. What is the result of print("5" * 3)
?
Answer:
It prints 555
because multiplying a string by an integer repeats the string.
7. What is a common issue when using mutable default arguments?
Answer:
Using a mutable object like a list or dictionary as a default argument can retain state between function calls, leading to unexpected behavior. For example, def add_item(item, lst=[]): lst.append(item); return lst
will use the same list across calls, accumulating items.
8. What does list(range(0))
return?
Answer:
An empty list: []
.
9. How does Python handle variable scope resolution?
Answer:
Python uses the LEGB rule: Local (within the current function), Enclosing (in outer functions for nested functions), Global (module-level variables), Built-in (Python’s built-in names like len
).
10. How do you handle exceptions in Python?
Answer:
Use a try-except
block. For example: try: x = 1 / 0; except ZeroDivisionError: print("Cannot divide by zero")
catches the error and executes the alternative code.
11. What’s wrong with the code: if x = 5:
?
Answer:
Assignment operator =
cannot be used in conditions. Use ==
for comparison.
12. What happens if you try to modify a string in Python?
Answer:
You get a TypeError
because strings are immutable in Python.
13. Explain the output: print("abc".capitalize())
Answer:
It prints Abc
– only the first character is made uppercase, rest are lowercase.
14. What is an f-string, and how is it used in Python?
Answer:
An f-string is a way to format strings using f"..."
, embedding expressions inside curly braces. Example: name = "Alice"; print(f"Hello, {name}!")
outputs Hello, Alice!
.
15. How can you check if a key exists in a dictionary?
Answer:
Use the in
operator: key in my_dict
.
16. What is the output of print(10 // 3)
?
Answer:
3
. The //
operator performs floor division.
17. What is the difference between append()
and extend()
?
Answer:
append()
adds the whole object as a single element, while extend()
adds each element of the iterable individually.
18. How do you read the contents of a text file in Python?
Answer:
Use open()
with a with
statement: with open("file.txt", "r") as file: content = file.read()
. This reads the entire file into content
.
19. How can you reverse a list without using loops?
Answer:
Using slicing: reversed_list = my_list[::-1]
.
20. What is the output of len("hello\nworld")
?
Answer:
11
. The newline character \n
counts as one character.
21. What is a lambda function?
Answer:
An anonymous function defined with the lambda
keyword. Example: lambda x: x + 1
.
22. Is Python statically typed or dynamically typed?
Answer:
Dynamically typed – types are determined at runtime.
23. What are type hints, and how might you use them in Python?
Answer:
Type hints specify expected variable types using annotations, improving code readability. Example: def add(a: int, b: int) -> int: return a + b
indicates integers as inputs and output.
24. What does dict.get("key", "default")
do?
Answer:
Returns the value for “key” if it exists in the dictionary; otherwise, returns “default”. If no default is provided, returns None
. Prevents KeyError
.
25. What does the following return: print([1, 2, 3] + [4])
?
Answer:
[1, 2, 3, 4]
. The +
operator concatenates the lists.
👋 Need top Python developers for your team? Interview this week!
Fill out the form to book a call with our team. We’ll match you to the top developers who meet your requirements, and you’ll be interviewing this week!
Intermediate Level (1–3 Years)
1. What are Python’s data model dunder methods, and why are they important?
Answer:
Dunder methods like __len__
, __str__
, and __add__
allow classes to emulate built-in types and integrate with Python syntax, such as len()
, str()
, or +
. They enable operator overloading and customization, making classes behave like native Python objects.
2. How do list comprehensions differ from generator expressions?
Answer:
List comprehensions (e.g., [x**2 for x in range(10)]
) return a full list in memory. Generator expressions (e.g., (x**2 for x in range(10))
) use lazy evaluation, returning a generator object, which is more memory-efficient for large datasets.
3. Explain the difference between @staticmethod
and @classmethod
.
Answer:
@staticmethod
defines a method that doesn’t access instance or class state. @classmethod
takes cls
as its first parameter, allowing access or modification of class state, useful for alternative constructors.
4. What is the output of the following code?
Answer:
def func(val, lst=[]):
lst.append(val)
return lst
print(func(1))
print(func(2))
Output: [1]
, [1, 2]
— due to the mutable default argument retaining state between calls.
5. What are Python’s descriptors?
Answer:
Descriptors are objects defining __get__
, __set__
, or __delete__
methods, controlling attribute access. They’re used in properties, class methods, and frameworks like Django ORM for customized attribute behavior.
6. What is the difference between isinstance()
and type()
?
Answer:
isinstance()
considers inheritance, checking if an object is an instance of a class or its subclasses. type()
checks exact type without inheritance. Prefer isinstance()
for robust type checks.
7. What is a closure in Python?
Answer:
A closure is a function that retains access to variables from its enclosing lexical scope, even after that scope is gone. Example: def outer(x): def inner(): return x; return inner
.
8. Why does this produce an error? {[1, 2]: "value"}
Answer:
Lists are mutable and unhashable, so they cannot be used as dictionary keys, which require immutable, hashable objects like strings or tuples.
9. What is the difference between yield
and return
?
Answer:
return
terminates a function and sends a value back. yield
pauses execution, sends a value, and resumes on the next call, enabling generators.
10. Explain the GIL in Python.
Answer:
The Global Interpreter Lock (GIL) ensures only one thread executes Python bytecode at a time in CPython, limiting true parallelism in multithreading but simplifying memory management.
11. What is the output of this?
Answer:
x = [1, 2, 3]
y = x
x += [4, 5]
print(y)
Output: [1, 2, 3, 4, 5]
— +=
mutates the list in-place, affecting y
since it references the same object.
12. What is monkey patching in Python?
Answer:
Monkey patching is dynamically modifying or extending code at runtime, such as adding or changing methods in a module or class.
13. What is a metaclass?
Answer:
A metaclass is the class of a class, controlling class creation. It’s used for advanced customization, such as in ORMs or frameworks, by defining __new__
or __init__
.
14. When should you use a namedtuple instead of a dictionary?
Answer:
Use namedtuple
for immutable, lightweight objects with named fields and dot notation (e.g., point.x
) when you don’t need dynamic keys or mutability, unlike dictionaries.
15. What is the purpose of the __slots__
declaration?
Answer:
__slots__
restricts dynamic attribute creation, saving memory by avoiding per-instance __dict__
. It’s useful for classes with many instances.
16. How does argument unpacking work in Python?
Answer:
*args
unpacks iterables into positional arguments, and **kwargs
unpacks dictionaries into keyword arguments, allowing flexible function calls.
17. What’s the difference between deepcopy()
and copy()
?
Answer:
copy()
creates a shallow copy, duplicating only the top-level object. deepcopy()
recursively copies nested objects, ensuring full independence.
18. What is a context manager?
Answer:
A context manager implements __enter__
and __exit__
, used with with
statements to manage resources like files, ensuring proper cleanup.
19. How are Python’s set
and frozenset
different?
Answer:
set
is mutable, allowing additions/removals. frozenset
is immutable and hashable, suitable for dictionary keys or set elements.
20. What does functools.lru_cache
do?
Answer:
functools.lru_cache
caches function results based on arguments, using a least-recently-used strategy to avoid recomputing expensive calls.
21. What are Python wheels?
Answer:
Wheels are a binary packaging format for Python, enabling faster installation by avoiding source compilation, unlike older .egg
files.
22. When would you use enumerate()
?
Answer:
Use enumerate()
to iterate over an iterable while accessing both index and value, e.g., for i, val in enumerate(lst)
.
23. How does Python’s garbage collector work?
Answer:
Python uses reference counting to free objects when their reference count is zero, plus a cyclic garbage collector to handle reference cycles.
24. What is the difference between assert
and raise
?
Answer:
assert
raises AssertionError
for debugging conditions, disabled in optimized mode. raise
explicitly throws any exception for error handling.
25. What does locals()
return?
Answer:
A dictionary of the current local symbol table, useful for debugging or introspection within a function.
26. What is the output of sorted(['a', 'abc', 'ab'], key=len)
?
Answer:
['a', 'ab', 'abc']
— The key=len
sorts strings by their length.
27. How do you make a Python class iterable?
Answer:
Implement __iter__()
to return an iterator (often self
) and __next__()
to define iteration behavior.
28. What is the use of the nonlocal
keyword?
Answer:
nonlocal
allows modifying a variable in the nearest enclosing (non-global) scope, useful in nested functions.
29. What does collections.defaultdict
do?
Answer:
collections.defaultdict
provides a default value for missing keys using a factory function (e.g., list
, int
), avoiding KeyError
.
30. What’s the difference between __str__
and __repr__
?
Answer:
__str__
provides a human-readable string representation; __repr__
provides an unambiguous representation, often for debugging.
31. What is duck typing in Python?
Answer:
Duck typing focuses on an object’s behavior (methods/attributes) rather than its type. “If it quacks like a duck, it’s a duck.”
32. What is a Python decorator, and how do you create one?
Answer:
A decorator is a function that wraps another function to extend its behavior. Example: def my_decorator(func): def wrapper(): print("Before"); func(); print("After"); return wrapper
.
33. What are Abstract Base Classes (ABCs) in Python?
Answer:
ABCs, from the abc
module, define interfaces with abstract methods that subclasses must implement, ensuring consistent behavior across classes.
34. Why are tuples more memory-efficient than lists?
Answer:
Tuples are immutable, so they have a fixed size and no overhead for dynamic resizing, unlike lists, which allocate extra space for potential growth.
35. How do you safely access a nested dictionary key?
Answer:
Use chained get()
calls, e.g., data.get('a', {}).get('b')
, or try-except
to handle missing keys gracefully.
36. How are tuples different from lists in terms of usage?
Answer:
Tuples are immutable, used for fixed data (e.g., coordinates). Lists are mutable, used for collections that may change.
37. What’s the advantage of using with open()
?
Answer:
It ensures files are closed after use, even if exceptions occur, via a context manager.
38. How do you use async/await in Python?
Answer:
async def
defines an asynchronous function, and await
pauses execution until a coroutine completes. Example: async def fetch(): return await asyncio.sleep(1)
.
39. How do you merge two dictionaries in Python 3.9+?
Answer:
Use the |
operator: merged = dict1 | dict2
, or dict1.update(dict2)
for older versions.
40. What does re.split(r"(?<=\\w)\\s+", "Hello world!")
return?
Answer:
['Hello', 'world!']
— The regex uses a positive lookbehind to split on whitespace after a word character, preserving punctuation.
41. Why are Python strings immutable?
Answer:
Immutability ensures strings are hashable (for dictionary keys), enables interning for efficiency, and prevents unintended modifications.
42. What is __name__ == "__main__"
used for?
Answer:
It ensures code runs only when the file is executed directly, not when imported as a module.
43. What does sorted()
return if used on a dictionary?
Answer:
A sorted list of the dictionary’s keys.
44. How does Python handle method resolution in multiple inheritance?
Answer:
Python uses C3 linearization (Method Resolution Order) to ensure a consistent, predictable method lookup path in multiple inheritance.
45. What is a weak reference?
Answer:
A weak reference, from the weakref
module, doesn’t increase an object’s reference count, allowing it to be garbage-collected when no strong references remain.
46. What’s the use of the __call__
method?
Answer:
__call__
makes an object callable like a function, useful for function-like objects or decorators.
47. What is the effect of from module import *
?
Answer:
It imports all public names from a module’s __all__
(if defined) or all non-underscore names, but can cause namespace pollution.
48. What does dir()
return?
Answer:
A list of an object’s attributes and methods, including inherited and dunder methods, useful for introspection.
49. What is the output of list(zip([1, 2], ['a', 'b']))
?
Answer:
[(1, 'a'), (2, 'b')]
— zip()
pairs elements from the input iterables into tuples.
50. What is the purpose of the dataclasses
module?
Answer:
The dataclasses
module simplifies class creation by automatically generating boilerplate methods like __init__
, __repr__
, and __eq__
for data-centric classes.

Hire Top LATAM Developers: Guide
We’ve prepared this guide that covers benefits, costs, recruitment, and remote team management to a succesful hiring of developers in LATAM.
Fill out the form to get our guide.
Advanced Level (3+ Years)
1. What are Python’s memory management mechanisms?
Answer:
Python uses reference counting, a cyclic garbage collector (via the gc
module), and memory pools for PyObject
allocation. The gc
module allows explicit control, and tools like tracemalloc
help debug memory usage.
2. How does Python handle tail recursion?
Answer:
Python does not optimize tail recursion, leading to a RecursionError
for deep recursive calls. Developers can use iteration or manual stack management instead.
3. Explain the Python data model and its impact on customization.
Answer:
The Python data model uses dunder methods (e.g., __add__
for +
, __getitem__
for indexing) to enable operator overloading and integration with language syntax, allowing custom classes to behave like built-in types.
4. What is the difference between __new__
and __init__
?
Answer:
__new__
creates and returns a new instance, used for immutable types or metaclasses. __init__
initializes an already-created instance.
5. How does Python implement method resolution order (MRO)?
Answer:
Python uses the C3 linearization algorithm to define a consistent MRO for classes with multiple inheritance, accessible via __mro__
.
6. What are metaclasses used for?
Answer:
Metaclasses control class creation, enabling attribute validation, method injection, or interface enforcement, as seen in ORMs like Django’s Model
.
7. What is the significance of __slots__
in high-performance applications?
Answer:
__slots__
eliminates per-instance __dict__
, reducing memory usage and speeding up attribute access, ideal for classes with many instances.
8. What’s the difference between weak references and strong references?
Answer:
Strong references prevent garbage collection by incrementing reference counts. Weak references (via weakref
) allow collection when no strong references remain.
9. What happens if you override __eq__
without __hash__
?
Answer:
Instances become unhashable, preventing their use in sets or as dictionary keys unless __hash__
is explicitly defined.
10. Explain the use of memoryview and its advantages.
Answer:
memoryview
enables zero-copy access to binary data, allowing efficient slicing and manipulation without duplicating memory, ideal for performance-critical code.
11. What is the difference between multiprocessing and multithreading in Python?
Answer:
Multithreading shares memory but is limited by the GIL for CPU-bound tasks. Multiprocessing uses separate processes, bypassing the GIL for true parallelism.
12. How do asyncio coroutines differ from threads?
Answer:
Coroutines are cooperative, single-threaded, and yield control via await
. Threads are pre-emptive, running concurrently but constrained by the GIL.
13. What is the purpose of __getattr__
vs __getattribute__
?
Answer:
__getattribute__
is called for all attribute access. __getattr__
is a fallback for attributes not found via normal lookup.
14. Describe Python’s Global Interpreter Lock (GIL) in CPython.
Answer:
The GIL ensures only one thread executes Python bytecode at a time, preventing race conditions but limiting CPU-bound parallelism in CPython.
15. How would you implement a plugin architecture in Python?
Answer:
Use dynamic imports (importlib
), registration decorators, or abstract base classes to define plugin interfaces and load modules dynamically.
16. What is structural pattern matching in Python 3.10+?
Answer:
The match/case
statement enables pattern-based control flow, supporting destructuring and type matching, similar to switch statements.
17. How do you prevent race conditions in async code?
Answer:
Use asyncio.Lock
, asyncio.Semaphore
, or other synchronization primitives to ensure atomic access to shared resources.
18. What’s the benefit of immutability in concurrent programs?
Answer:
Immutable objects prevent race conditions and side effects, simplifying reasoning and ensuring thread-safety in concurrent code.
19. What are the implications of monkey patching in production?
Answer:
Monkey patching can introduce unpredictability, maintenance challenges, and bugs, though it’s useful for hot fixes or testing.
20. What is the purpose of contextvars
in async code?
Answer:
contextvars
provide context-local storage for async code, allowing coroutines to maintain isolated state, unlike thread-local storage.
21. How can you speed up numerical computations in Python?
Answer:
Use NumPy for C-backed arrays, Numba for JIT compilation, Cython for compiled extensions, or parallelize with multiprocessing
.
22. How does Python’s type system handle dynamic typing internally?
Answer:
Python uses a dynamic type system where objects carry type information via __class__
. The interpreter resolves types at runtime using C-level PyObject
structures.
23. What’s the difference between shallow copy and deep copy in terms of performance?
Answer:
Shallow copies (copy.copy
) are faster, duplicating only the top-level object. Deep copies (copy.deepcopy
) are slower, recursively copying nested objects.
24. How do memory leaks occur in Python?
Answer:
Memory leaks arise from circular references not cleared by the GC, global scope references, or C extension bugs. Use tracemalloc
to diagnose.
25. How does Python’s __import__
function work?
Answer:
__import__
is the low-level function behind import
, allowing dynamic module loading with customizable import behavior via arguments.
26. What is function currying and how can it be implemented in Python?
Answer:
Currying transforms a multi-argument function into a chain of single-argument functions. Implement using functools.partial
or nested functions.
27. How can you introspect a Python function to see its parameters?
Answer:
Use the inspect
module: inspect.signature(func)
or inspect.getfullargspec(func)
to retrieve parameter details.
28. What’s the role of the ast
module?
Answer:
The ast
module parses Python source into an abstract syntax tree, enabling static analysis, code transformation, or custom linting.
29. How do decorators with arguments work?
Answer:
Decorators with arguments use three nested functions: outer (takes arguments), decorator (returns wrapper), and wrapper (executes the function).
30. Explain the difference between generators and coroutines.
Answer:
Generators produce values via yield
for iteration. Coroutines (async def
) handle asynchronous I/O with await
, designed for concurrency.
31. What is the difference between @property
and descriptors?
Answer:
@property
is a simplified descriptor interface. Descriptors (__get__
, __set__
, etc.) offer finer control over attribute access.
32. What’s the purpose of yield from
?
Answer:
yield from
delegates yielding to another generator or iterable, simplifying nested generator logic.
33. When would you use a metaclass in real applications?
Answer:
Metaclasses are used for auto-registering classes, validating attributes, injecting methods, or enforcing interfaces, common in frameworks like Django.
34. What are some pitfalls of using eval()
?
Answer:
eval()
executes arbitrary code, posing security risks with untrusted input and potential performance issues due to parsing overhead.
35. How does Python implement dynamic dispatch?
Answer:
Dynamic dispatch uses the MRO and dunder methods to resolve method calls at runtime based on the object’s class hierarchy.
36. What is the purpose of __annotations__
?
Answer:
__annotations__
stores type hints for functions and variables, used by static type checkers like mypy for validation and documentation.
37. What is the difference between abc.ABC
and Protocol
from typing?
Answer:
abc.ABC
enforces nominal subtyping with explicit inheritance. typing.Protocol
supports structural subtyping for duck typing in static analysis.
38. How can you intercept object creation in Python?
Answer:
Override __new__()
in a class or metaclass to customize object instantiation logic before __init__
is called.
39. How is the CPython interpreter different from PyPy?
Answer:
CPython, written in C, is the reference interpreter. PyPy, written in RPython, uses a JIT compiler for better performance in long-running programs.
40. What’s the difference between a context manager and a decorator?
Answer:
Context managers (__enter__
/__exit__
) handle resource lifecycles with with
. Decorators wrap functions to modify behavior.
41. What is the purpose of __dir__()
?
Answer:
__dir__()
customizes the attributes returned by dir(obj)
, allowing control over introspection output.
42. What’s the role of bytecode in Python?
Answer:
Python source is compiled to bytecode (.pyc files), executed by the Python Virtual Machine (PVM), enabling portability and faster execution.
43. How can you profile and optimize Python code?
Answer:
Use cProfile
, line_profiler
, or memory_profiler
for profiling. Optimize with better algorithms, Numba, Cython, or multiprocessing.
44. How can you cache function calls without using external libraries?
Answer:
Implement a custom memoization decorator using a dictionary to store results, e.g., def memoize(func): cache = {}; return lambda *args: cache.setdefault(args, func(*args))
.
45. How can you inspect or modify Python bytecode?
Answer:
Use the dis
module to inspect bytecode and libraries like bytecode
or codegen
to modify it programmatically.
46. How can you serialize objects with circular references?
Answer:
Use pickle
or dill
, which handle circular references natively. Standard json
requires custom encoders to avoid errors.
47. How can you customize Python’s memory allocator?
Answer:
Override CPython’s allocator using the C API’s PyMem_RawMalloc
or third-party allocators like jemalloc for performance tuning.
48. Why is asyncio.run()
preferred in Python 3.7+?
Answer:
asyncio.run()
simplifies coroutine execution by managing the event loop, ensuring proper setup and cleanup.
49. How do you handle OS signals in Python?
Answer:
Use the signal
module to register handlers for signals like SIGINT
, e.g., signal.signal(signal.SIGINT, handler)
, for graceful shutdowns.
50. How can you extend Python with C?
Answer:
Use the Python C API to write modules in C, or use Cython/ ctypes for simpler integration, boosting performance for critical sections.