Skip to content

Latest commit

 

History

History
84 lines (68 loc) · 4.58 KB

File metadata and controls

84 lines (68 loc) · 4.58 KB

💼 Python Technical Interview Prep Guide

This guide covers core concepts, memory models, and standard questions frequently asked during senior and mid-level Python developer interviews.


1. Memory Management & Object Models

Q1: What is the difference between Mutable and Immutable types?

  • Immutable Types: Once created, their value cannot be changed. Any operation that alters the value results in the creation of a new object in memory.
    • Examples: int, float, str, tuple, frozenset, bool.
  • Mutable Types: Their internal state or value can be changed in place without changing the object's identity (memory address).
    • Examples: list, dict, set, bytearray.
  • Key Interview Gotcha: Modifying a list passed into a function alters the caller's list because lists are passed by assignment (reference sharing).
    def append_item(lst=[]):  # WARNING: Mutable default arguments are evaluated ONCE at function definition!
        lst.append("item")
        return lst

Q2: How does Python manage memory?

Python uses two main mechanisms for memory allocation and cleanup:

  1. Reference Counting:
    • Every Python object keeps track of how many variables or collections reference it.
    • When an object's reference count drops to 0, its memory is immediately deallocated.
  2. Garbage Collector (Generational GC):
    • Used to detect and clean up reference cycles (e.g., Object A references Object B, and Object B references Object A, but both are unreachable from the root scope).
    • Python categorizes objects into 3 generations (Gen 0, 1, and 2) based on how long they have survived. Gen 0 is collected most frequently.

2. Concurrency & Parallelism

Q3: What is the GIL (Global Interpreter Lock)?

  • Definition: The GIL is a mutex (lock) in the standard CPython implementation that prevents multiple native threads from executing Python bytecodes at once.
  • Why does it exist? It simplifies CPython implementation by making memory management (specifically reference counting) thread-safe without needing granular locking.
  • How to bypass the GIL?
    • Use the multiprocessing module (creates separate OS processes, each with its own interpreter and GIL).
    • Outsource heavy computations to C extensions (like numpy, pandas) which release the GIL during execution.
    • Use alternative interpreters like Jython or IronPython (which do not have a GIL).

3. Iterators, Generators & Decorators

Q4: What is the difference between an Iterator and a Generator?

  • Iterable: An object that can return its elements one at a time (implements __iter__()).
  • Iterator: An object that implements __next__() and __iter__(). It keeps track of its current state and raises StopIteration when elements run out.
  • Generator: A simpler way to write an iterator using a function and the yield keyword.
    • Instead of computing all values upfront and storing them in memory (like a list), a generator yields values lazily on demand.
    • Memory Efficiency: Generating 1 million items sequentially via a generator takes $O(1)$ memory, whereas a list takes $O(n)$.

Q5: How do Decorators work in Python?

  • A decorator is a function that takes another function as an argument, adds some behavior, and returns a new function without modifying the original function's source code.
  • It leverages closures to retain access to variables in the outer enclosing scope.
  • Basic template:
    def my_decorator(func):
        def wrapper(*args, **kwargs):
            # Do something before func runs
            result = func(*args, **kwargs)
            # Do something after
            return result
        return wrapper

4. Common Coding & Design Questions

Q6: Explain "Duck Typing" in Python.

"If it walks like a duck and quacks like a duck, it's a duck."

  • Python does not check types at compile-time. Instead, it checks for the presence of methods or properties at runtime.
  • If an object has a .read() method, Python will treat it as a file-like object, regardless of whether it inherits from io.IOBase.

Q7: What is the difference between is and ==?

  • == compares values (calls __eq__ under the hood) to check if they are equivalent.
  • is compares identities (memory addresses using id()) to check if they refer to the exact same object in memory.
    a = [1, 2, 3]
    b = [1, 2, 3]
    print(a == b)  # True (same values)
    print(a is b)  # False (different objects in memory)