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!

Request for Service


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.


LATAM-Image-V2.png

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.

Gated content


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.