Interview Q&A · 104 questions · 21 answered publicly

Python Developer Interview Questions

Ordered by how often they're asked. Sign in free to see every answer, rate your confidence and run timed mock interviews.

  1. Most asked Explain mutable vs immutable in Python.

    Summary

    Mutable objects can change in place after creation; immutable objects cannot change their value once created.

    Longer Answer

    Lists, dictionaries, and sets are mutable, so aliases to the same object can observe changes made through any reference. Integers, strings, tuples, frozensets, and bytes are immutable, so operations create new objects or reuse existing immutable values.

    This matters for default arguments, hashing, caching, defensive copying, and API design. A common bug is using a mutable default such as [] in a function signature, which is shared across calls.

    Key Points

    • Lists, dictionaries, and sets are mutable, so aliases to the same object can observe changes made through any reference
    • Integers, strings, tuples, frozensets, and bytes are immutable, so operations create new objects or reuse existing immutable values
    • This matters for default arguments, hashing, caching, defensive copying, and API design
    • For 'Explain mutable vs immutable in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    This matters for default arguments, hashing, caching, defensive copying, and API design. A common bug is using a mutable default such as [] in a function signature, which is shared across calls

    Comparison / Tradeoffs

    Aspect Notes
    Core idea Mutable objects can change in place after creation; immutable objects cannot change their value once created.
    Practical tradeoff For 'Explain mutable vs immutable in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    This matters for default arguments, hashing, caching, defensive copying, and API design. A common bug is using a mutable default such as [] in a function signature, which is shared across calls. |

    Permalink

  2. Most asked Explain is vs == in Python.

    Summary

    == checks value equality, while is checks whether two variables reference the exact same object.

    Longer Answer

    Classes can customize == through eq, so two different objects can compare equal. The is operator cannot be customized; it compares object identity, which is why it is appropriate for sentinels such as None, NotImplemented, and custom singleton markers.

    Do not use is for strings, integers, or other values just because it appears to work in a REPL. Interning and caching are implementation details and can make identity checks pass accidentally.

    Key Points

    • Classes can customize == through eq, so two different objects can compare equal
    • The is operator cannot be customized; it compares object identity, which is why it is appropriate for sentinels such as None, NotImplemented, and custom singleton markers
    • Do not use is for strings, integers, or other values just because it appears to work in a REPL
    • For 'Explain is vs == in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    Do not use is for strings, integers, or other values just because it appears to work in a REPL. Interning and caching are implementation details and can make identity checks pass accidentally

    Comparison / Tradeoffs

    Aspect Notes
    Core idea == checks value equality, while is checks whether two variables reference the exact same object.
    Practical tradeoff Classes can customize == through eq, so two different objects can compare equal.

    Permalink

  3. Most asked Explain generators in Python.

    Summary

    Generators produce values lazily, one at a time, using yield or generator expressions.

    Longer Answer

    A generator function returns a generator object instead of running immediately. Each call to next resumes execution until the next yield, preserving local state between iterations. This makes generators excellent for streaming large files, pipelines, and infinite sequences.

    The tradeoff is one-pass consumption. Once a generator is exhausted, it must be recreated if values are needed again. Also, exceptions and resource cleanup should be handled carefully, often with context managers around the generator usage.

    Key Points

    • A generator function returns a generator object instead of running immediately
    • Each call to next resumes execution until the next yield, preserving local state between iterations
    • This makes generators excellent for streaming large files, pipelines, and infinite sequences
    • For 'Explain generators in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    The tradeoff is one-pass consumption. Once a generator is exhausted, it must be recreated if values are needed again. Also, exceptions and resource cleanup should be handled carefully, often with context managers around the generator usage

    Comparison / Tradeoffs

    Aspect Notes
    Core idea Generators produce values lazily, one at a time, using yield or generator expressions.
    Practical tradeoff A generator function returns a generator object instead of running immediately.

    Permalink

  4. Most asked Explain decorators in Python.

    Summary

    A decorator is a callable that takes a function or class and returns a modified or wrapped object.

    Longer Answer

    Decorators are executed at definition time, not each time the function is called. They are widely used for routing, authorization, caching, retries, validation, instrumentation, and test fixtures.

    When wrapping functions, use functools.wraps so metadata such as name, doc, annotations, and introspection behavior are preserved. Be careful with decorators that hide arguments, swallow exceptions, or introduce global state.

    Key Points

    • Decorators are executed at definition time, not each time the function is called
    • They are widely used for routing, authorization, caching, retries, validation, instrumentation, and test fixtures
    • When wrapping functions, use functools.wraps so metadata such as name, doc, annotations, and introspection behavior are preserved
    • For 'Explain decorators in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    When wrapping functions, use functools.wraps so metadata such as name, doc, annotations, and introspection behavior are preserved. Be careful with decorators that hide arguments, swallow exceptions, or introduce global state

    Comparison / Tradeoffs

    Aspect Notes
    Core idea A decorator is a callable that takes a function or class and returns a modified or wrapped object.
    Practical tradeoff For 'Explain decorators in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    When wrapping functions, use functools.wraps so metadata such as name, doc, annotations, and introspection behavior are preserved. Be careful with decorators that hide arguments, swallow exceptions, or introduce global state. |

    Permalink

  5. Most asked Explain context managers in Python.

    Summary

    Context managers define setup and cleanup around a block, usually through the with statement.

    Longer Answer

    An object can implement enter and exit, or a function can use contextlib.contextmanager to yield control. The cleanup runs even if the block raises, which makes context managers ideal for files, locks, database sessions, transactions, temporary directories, and patched test state.

    A strong answer mentions exception behavior: exit receives exception details and can suppress the exception only by returning True. Most context managers should not suppress exceptions unless that is their explicit purpose.

    Key Points

    • An object can implement enter and exit, or a function can use contextlib.contextmanager to yield control
    • The cleanup runs even if the block raises, which makes context managers ideal for files, locks, database sessions, transactions, temporary directories, and patched test state
    • A strong answer mentions exception behavior: exit receives exception details and can suppress the exception only by returning True
    • For 'Explain context managers in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    A strong answer mentions exception behavior: exit receives exception details and can suppress the exception only by returning True. Most context managers should not suppress exceptions unless that is their explicit purpose

    Comparison / Tradeoffs

    Aspect Notes
    Core idea Context managers define setup and cleanup around a block, usually through the with statement.
    Practical tradeoff For 'Explain context managers in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    A strong answer mentions exception behavior: exit receives exception details and can suppress the exception only by returning True. Most context managers should not suppress exceptions unless that is their explicit purpose. |

    Permalink

  6. Most asked Explain GIL in Python.

    Summary

    In CPython, the Global Interpreter Lock allows only one thread at a time to execute Python bytecode in a process.

    Longer Answer

    The GIL simplifies memory management and protects interpreter internals, but it limits CPU-bound parallelism with Python threads. Threads can still be useful for I/O-bound work because blocking I/O releases the GIL, and some C extensions release it during heavy native computation.

    For CPU-bound Python work, use multiprocessing, native extensions, vectorized libraries, or distributed workers. For I/O-bound services, threads or asyncio can still scale well if blocking calls and connection pools are managed correctly.

    Key Points

    • The GIL simplifies memory management and protects interpreter internals, but it limits CPU-bound parallelism with Python threads
    • Threads can still be useful for I/O-bound work because blocking I/O releases the GIL, and some C extensions release it during heavy native computation
    • For CPU-bound Python work, use multiprocessing, native extensions, vectorized libraries, or distributed workers
    • For 'Explain GIL in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    For CPU-bound Python work, use multiprocessing, native extensions, vectorized libraries, or distributed workers. For I/O-bound services, threads or asyncio can still scale well if blocking calls and connection pools are managed correctly

    Comparison / Tradeoffs

    Aspect Notes
    Core idea In CPython, the Global Interpreter Lock allows only one thread at a time to execute Python bytecode in a process.
    Practical tradeoff For 'Explain GIL in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    For CPU-bound Python work, use multiprocessing, native extensions, vectorized libraries, or distributed workers. For I/O-bound services, threads or asyncio can still scale well if blocking calls and connection pools are managed correctly. |

    Permalink

  7. Most asked Explain threading vs multiprocessing vs asyncio in Python.

    Summary

    Use threading for blocking I/O concurrency, multiprocessing for CPU parallelism, and asyncio for high-concurrency non-blocking I/O.

    Longer Answer

    Threads share memory inside one process and are straightforward with blocking libraries, but CPU-bound Python bytecode is constrained by the GIL in CPython. Multiprocessing uses separate processes, bypassing the GIL for CPU work at the cost of IPC, serialization, startup, and memory overhead.

    asyncio uses an event loop and cooperative multitasking. It can handle many network operations efficiently, but blocking code will stall the loop unless moved to a thread/process pool or replaced with async-aware libraries.

    Key Points

    • Threads share memory inside one process and are straightforward with blocking libraries, but CPU-bound Python bytecode is constrained by the GIL in CPython
    • Multiprocessing uses separate processes, bypassing the GIL for CPU work at the cost of IPC, serialization, startup, and memory overhead
    • asyncio uses an event loop and cooperative multitasking
    • For 'Explain threading vs multiprocessing vs asyncio in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    asyncio uses an event loop and cooperative multitasking. It can handle many network operations efficiently, but blocking code will stall the loop unless moved to a thread/process pool or replaced with async-aware libraries

    Comparison / Tradeoffs

    Aspect Notes
    Core idea Use threading for blocking I/O concurrency, multiprocessing for CPU parallelism, and asyncio for high-concurrency non-blocking I/O.
    Practical tradeoff For 'Explain threading vs multiprocessing vs asyncio in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    asyncio uses an event loop and cooperative multitasking. It can handle many network operations efficiently, but blocking code will stall the loop unless moved to a thread/process pool or replaced with async-aware libraries. |

    Permalink

  8. Most asked Backend Python interview: explain N+1 queries.

    Summary

    N+1 queries happen when code loads one set of rows and then issues an extra query for each row, causing query count to grow with result size.

    Longer Answer

    For example, fetching 100 users and then lazily fetching each user's orders produces 101 queries. This often passes tests with small fixtures but fails under production latency and database load.

    Fixes include eager loading, joins, select-in loading, prefetching, batching, explicit projections, and endpoint-specific query design. Also add query count checks or tracing so regressions are visible.

    Key Points

    • For example, fetching 100 users and then lazily fetching each user's orders produces 101 queries
    • This often passes tests with small fixtures but fails under production latency and database load
    • Fixes include eager loading, joins, select-in loading, prefetching, batching, explicit projections, and endpoint-specific query design
    • For 'Backend Python interview: explain N+1 queries.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    Fixes include eager loading, joins, select-in loading, prefetching, batching, explicit projections, and endpoint-specific query design. Also add query count checks or tracing so regressions are visible

    Comparison / Tradeoffs

    Aspect Notes
    Core idea N+1 queries happen when code loads one set of rows and then issues an extra query for each row, causing query count to grow with result size.
    Practical tradeoff For 'Backend Python interview: explain N+1 queries.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    Fixes include eager loading, joins, select-in loading, prefetching, batching, explicit projections, and endpoint-specific query design. Also add query count checks or tracing so regressions are visible. |

    Permalink

  9. Most asked Backend Python interview: explain authN vs authZ.

    Summary

    Authentication proves who the user or service is; authorization decides what that identity is allowed to do.

    Longer Answer

    Authentication uses credentials or tokens such as passwords, OAuth flows, API keys, mutual TLS, or session cookies. Authorization applies policies such as roles, permissions, ownership checks, scopes, attributes, or relationship-based access.

    A common production bug is authenticating a user and then forgetting object-level authorization. Every sensitive operation should check both the identity and whether it can access the specific resource.

    Key Points

    • Authentication uses credentials or tokens such as passwords, OAuth flows, API keys, mutual TLS, or session cookies
    • Authorization applies policies such as roles, permissions, ownership checks, scopes, attributes, or relationship-based access
    • A common production bug is authenticating a user and then forgetting object-level authorization
    • For 'Backend Python interview: explain authN vs authZ.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    A common production bug is authenticating a user and then forgetting object-level authorization. Every sensitive operation should check both the identity and whether it can access the specific resource

    Comparison / Tradeoffs

    Aspect Notes
    Core idea Authentication proves who the user or service is; authorization decides what that identity is allowed to do.
    Practical tradeoff For 'Backend Python interview: explain authN vs authZ.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    A common production bug is authenticating a user and then forgetting object-level authorization. Every sensitive operation should check both the identity and whether it can access the specific resource. |

    Permalink

  10. Most asked Backend Python interview: explain SQL injection prevention.

    Summary

    Prevent SQL injection by using parameterized queries or ORM query builders instead of string-concatenating user input into SQL.

    Longer Answer

    Parameterized queries send SQL structure separately from values, allowing the database driver to bind values safely. Escaping manually is fragile and should not be the main defense. ORMs help, but raw SQL inside ORM code can still be injectable if built with f-strings or concatenation.

    Also validate identifiers separately. Parameters protect values, not table names, column names, sort directions, or SQL fragments; those should come from allowlists.

    Key Points

    • Parameterized queries send SQL structure separately from values, allowing the database driver to bind values safely
    • Escaping manually is fragile and should not be the main defense
    • ORMs help, but raw SQL inside ORM code can still be injectable if built with f-strings or concatenation
    • For 'Backend Python interview: explain SQL injection prevention.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    Also validate identifiers separately. Parameters protect values, not table names, column names, sort directions, or SQL fragments; those should come from allowlists

    Comparison / Tradeoffs

    Aspect Notes
    Core idea Prevent SQL injection by using parameterized queries or ORM query builders instead of string-concatenating user input into SQL.
    Practical tradeoff For 'Backend Python interview: explain SQL injection prevention.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    Also validate identifiers separately. Parameters protect values, not table names, column names, sort directions, or SQL fragments; those should come from allowlists. |

    Permalink

  11. Most asked What is the late-binding closure gotcha in Python?

    Summary

    Closures capture variables, not values: lambdas created in a loop all see the variable's final value when called. Fix it by binding the current value as a default argument or using functools.partial.

    Longer Answer

    nonlocal lets inner functions rebind outer variables. This gotcha often appears in callback registration and list comprehensions creating lambdas.

    Code Example

    funcs = [lambda: i for i in range(3)]
    print([f() for f in funcs])        # [2, 2, 2]
    
    funcs = [lambda i=i: i for i in range(3)]
    print([f() for f in funcs])        # [0, 1, 2]
    

    Key Points

    • Closures look up variables at call time
    • Default args capture current values
    • functools.partial alternative
    • nonlocal to rebind

    Permalink

  12. Most asked Explain LEGB scoping in Python.

    Summary

    LEGB is Python's name lookup order: Local, Enclosing, Global, then Built-in scope.

    Longer Answer

    When Python resolves a name, it first checks the current function or comprehension local scope, then enclosing function scopes for closures, then the module global scope, and finally builtins. Assignment normally creates a local name unless global or nonlocal is declared.

    Interviewers look for the practical consequences: late binding in closures, UnboundLocalError when assigning to a name that was expected to be global, and when nonlocal is appropriate for nested functions.

    Key Points

    • When Python resolves a name, it first checks the current function or comprehension local scope, then enclosing function scopes for closures, then the module global scope, and finally builtins
    • Assignment normally creates a local name unless global or nonlocal is declared
    • Interviewers look for the practical consequences: late binding in closures, UnboundLocalError when assigning to a name that was expected to be global, and when nonlocal is appropriate for nested functions
    • For 'Explain LEGB scoping in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    Interviewers look for the practical consequences: late binding in closures, UnboundLocalError when assigning to a name that was expected to be global, and when nonlocal is appropriate for nested functions

    Comparison / Tradeoffs

    Aspect Notes
    Core idea LEGB is Python's name lookup order: Local, Enclosing, Global, then Built-in scope.
    Practical tradeoff For 'Explain LEGB scoping in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    Interviewers look for the practical consequences: late binding in closures, UnboundLocalError when assigning to a name that was expected to be global, and when nonlocal is appropriate for nested functions. |

    Permalink

  13. Most asked Explain *args and **kwargs in Python.

    Summary

    *args captures extra positional arguments as a tuple, and **kwargs captures extra keyword arguments as a dictionary.

    Longer Answer

    They are commonly used for wrappers, decorators, flexible APIs, and forwarding calls to another function. The same syntax can also unpack iterables and mappings at a call site, such as func(*items, **options).

    The risk is hiding the real API. For public code, use explicit parameters when possible and reserve *args/**kwargs for truly flexible forwarding or compatibility layers.

    Key Points

    • They are commonly used for wrappers, decorators, flexible APIs, and forwarding calls to another function
    • The same syntax can also unpack iterables and mappings at a call site, such as func(*items, **options)
    • The risk is hiding the real API
    • For 'Explain *args and **kwargs in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    The risk is hiding the real API. For public code, use explicit parameters when possible and reserve *args/**kwargs for truly flexible forwarding or compatibility layers

    Comparison / Tradeoffs

    Aspect Notes
    Core idea *args captures extra positional arguments as a tuple, and **kwargs captures extra keyword arguments as a dictionary.
    Practical tradeoff For 'Explain *args and **kwargs in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    The risk is hiding the real API. For public code, use explicit parameters when possible and reserve *args/**kwargs for truly flexible forwarding or compatibility layers. |

    Permalink

  14. Most asked Explain list/dict/set comprehensions in Python.

    Summary

    Comprehensions are concise expressions for building lists, dictionaries, and sets from iterables.

    Longer Answer

    A comprehension combines iteration, optional filtering, and expression transformation in one readable construct. They are often faster and clearer than manual append loops for simple transformations.

    The practical rule is to use comprehensions when they remain readable. If the expression needs complex branching, side effects, nested loops, logging, or exception handling, use a normal loop instead.

    Key Points

    • A comprehension combines iteration, optional filtering, and expression transformation in one readable construct
    • They are often faster and clearer than manual append loops for simple transformations
    • The practical rule is to use comprehensions when they remain readable
    • For 'Explain list/dict/set comprehensions in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    The practical rule is to use comprehensions when they remain readable. If the expression needs complex branching, side effects, nested loops, logging, or exception handling, use a normal loop instead

    Comparison / Tradeoffs

    Aspect Notes
    Core idea Comprehensions are concise expressions for building lists, dictionaries, and sets from iterables.
    Practical tradeoff If the expression needs complex branching, side effects, nested loops, logging, or exception handling, use a normal loop instead.

    Permalink

  15. Most asked Explain dataclasses in Python.

    Summary

    dataclasses generate common boilerplate for classes that primarily store data.

    Longer Answer

    The @dataclass decorator can generate init, repr, eq, ordering methods, defaults, default factories, frozen behavior, and post-init hooks. It is useful for configuration objects, DTOs, parsed records, and small domain values.

    The main pitfalls are mutable defaults and shallow immutability. Use field(default_factory=list) instead of defaulting to [], and understand that frozen=True prevents assignment to fields but does not deeply freeze referenced objects.

    Key Points

    • The @dataclass decorator can generate init, repr, eq, ordering methods, defaults, default factories, frozen behavior, and post-init hooks
    • It is useful for configuration objects, DTOs, parsed records, and small domain values
    • The main pitfalls are mutable defaults and shallow immutability
    • For 'Explain dataclasses in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    The main pitfalls are mutable defaults and shallow immutability. Use field(default_factory=list) instead of defaulting to [], and understand that frozen=True prevents assignment to fields but does not deeply freeze referenced objects

    Comparison / Tradeoffs

    Aspect Notes
    Core idea dataclasses generate common boilerplate for classes that primarily store data.
    Practical tradeoff Use field(default_factory=list) instead of defaulting to [], and understand that frozen=True prevents assignment to fields but does not deeply freeze referenced objects.

    Permalink

  16. Most asked Explain dunder methods in Python.

    Summary

    Dunder methods are special methods like len, iter, and eq that let objects participate in Python language protocols.

    Longer Answer

    Python syntax often maps to dunder methods: len(x) calls x.len, for loops use iter and next, equality uses eq, context managers use enter and exit, and arithmetic uses methods such as add.

    Implement dunder methods when your object truly behaves like the protocol. Do not add surprising operator behavior just because it is possible; it should make the object more Pythonic and predictable.

    Key Points

    • Python syntax often maps to dunder methods: len(x) calls x.len, for loops use iter and next, equality uses eq, context managers use enter and exit, and arithmetic uses methods such as add
    • Implement dunder methods when your object truly behaves like the protocol
    • Do not add surprising operator behavior just because it is possible; it should make the object more Pythonic and predictable
    • For 'Explain dunder methods in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    Implement dunder methods when your object truly behaves like the protocol. Do not add surprising operator behavior just because it is possible; it should make the object more Pythonic and predictable

    Comparison / Tradeoffs

    Aspect Notes
    Core idea Dunder methods are special methods like len, iter, and eq that let objects participate in Python language protocols.
    Practical tradeoff For 'Explain dunder methods in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    Implement dunder methods when your object truly behaves like the protocol. Do not add surprising operator behavior just because it is possible; it should make the object more Pythonic and predictable. |

    Permalink

  17. Most asked Explain deepcopy vs copy in Python.

    Summary

    copy.copy creates a shallow copy, while copy.deepcopy recursively copies nested objects.

    Longer Answer

    A shallow copy creates a new outer container but keeps references to the same nested objects. A deep copy recursively copies nested objects, using memoization to handle cycles and shared references.

    The right choice depends on ownership. If nested objects should remain shared, shallow copy is correct. If the copy must be independently mutable, deep copy may be needed, but it can be expensive and may copy more than intended.

    Key Points

    • A shallow copy creates a new outer container but keeps references to the same nested objects
    • A deep copy recursively copies nested objects, using memoization to handle cycles and shared references
    • The right choice depends on ownership
    • For 'Explain deepcopy vs copy in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    The right choice depends on ownership. If nested objects should remain shared, shallow copy is correct. If the copy must be independently mutable, deep copy may be needed, but it can be expensive and may copy more than intended

    Comparison / Tradeoffs

    Aspect Notes
    Core idea copy.copy creates a shallow copy, while copy.deepcopy recursively copies nested objects.
    Practical tradeoff For 'Explain deepcopy vs copy in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    The right choice depends on ownership. If nested objects should remain shared, shallow copy is correct. If the copy must be independently mutable, deep copy may be needed, but it can be expensive and may copy more than intended. |

    Permalink

  18. Most asked Explain structural pattern matching (`match`/`case`).

    Summary

    Python 3.10's match statement compares a subject against patterns: literals, captures, sequences, mappings, class patterns with attributes, OR patterns (|), guards (if), and wildcards (_), destructuring data as it matches.

    Longer Answer

    It shines for parsing commands, ASTs, JSON-like messages and state machines. It's not a C-style switch: bare names capture values (use dotted names or literals for constants), and the first matching case wins.

    Code Example

    def handle(event: dict) -> str:
        match event:
            case {"type": "click", "pos": (x, y)}:
                return f"click at {x},{y}"
            case {"type": "key", "key": "q" | "Q"}:
                return "quit"
            case {"type": "resize", "size": (w, h)} if w * h > 1_000_000:
                return "large resize"
            case _:
                return "ignored"
    

    Key Points

    • Destructures sequences, mappings, classes
    • Guards with if
    • Bare names capture (beware)
    • First match wins

    Permalink

  19. Most asked What do EAFP and LBYL mean, and which is more Pythonic?

    Summary

    EAFP ('Easier to Ask Forgiveness than Permission') tries the operation and handles exceptions; LBYL ('Look Before You Leap') checks conditions first. EAFP is generally considered more Pythonic and avoids race conditions (e.g., a file deleted between check and open).

    Longer Answer

    Use EAFP with narrow except clauses. LBYL is fine when failures are common and checks are cheap, or when exceptions would be costly in a hot loop.

    Key Points

    • EAFP: try/except
    • LBYL: check first
    • EAFP avoids TOCTOU races
    • Keep except clauses narrow

    Permalink

  20. Most asked Walk through the request/response lifecycle in Django, and explain why middleware order matters.

    Summary

    The WSGI or ASGI handler builds an HttpRequest; it passes down through MIDDLEWARE in order; the URL resolver picks the view; process_view hooks run; the view returns a response (process_exception on errors, template responses rendered); the response passes back up through the middleware in reverse order; request_finished fires. Order matters because middleware can only use what earlier middleware set up, for example request.user from AuthenticationMiddleware, which needs SessionMiddleware before it.

    Longer Answer

    A custom middleware placed above AuthenticationMiddleware sees no user, so an audit log records everyone as anonymous. Request-phase code runs top-down and response-phase code bottom-up.

    Key Points

    • A custom middleware placed above AuthenticationMiddleware sees no user, so an audit log records everyone as anonymous
    • Request-phase code runs top-down and response-phase code bottom-up
    • What interviewers look for

    The onion model and a concrete ordering dependency

    • Use the answer to connect the concept back to a realistic production or interview scenario for 'Walk through the request/response lifecycle in Django, and explain why middleware order matters.'

    Comparison / Tradeoffs

    Aspect Notes
    Core idea The WSGI or ASGI handler builds an HttpRequest; it passes down through MIDDLEWARE in order; the URL resolver picks the view; process_view hooks run; the view returns a response (process_exception on errors, template responses rendered); the response passes back up through the middleware in reverse order; request_finished fires. Order matters because middleware can only use what earlier middleware set up, for example request.user from AuthenticationMiddleware, which needs SessionMiddleware before it.
    Practical tradeoff ## What interviewers look for

    The onion model and a concrete ordering dependency. |

    Permalink

  21. Most asked Explain MRO / C3 in Python.

    Summary

    MRO is the method resolution order Python uses to search classes in inheritance hierarchies, computed with the C3 linearization algorithm.

    Longer Answer

    For a class with multiple inheritance, Python must choose a consistent order that preserves local precedence and monotonicity. You can inspect it with Class.mro or Class.mro(). super() follows this MRO, which is why cooperative multiple inheritance requires every class in the chain to call super correctly.

    MRO matters when using mixins. Good mixins should be small, documented, and cooperative; otherwise method names collide or parent methods are skipped unexpectedly.

    Key Points

    • For a class with multiple inheritance, Python must choose a consistent order that preserves local precedence and monotonicity
    • You can inspect it with Class.mro or Class.mro()
    • super() follows this MRO, which is why cooperative multiple inheritance requires every class in the chain to call super correctly
    • For 'Explain MRO / C3 in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    MRO matters when using mixins. Good mixins should be small, documented, and cooperative; otherwise method names collide or parent methods are skipped unexpectedly

    Comparison / Tradeoffs

    Aspect Notes
    Core idea MRO is the method resolution order Python uses to search classes in inheritance hierarchies, computed with the C3 linearization algorithm.
    Practical tradeoff For 'Explain MRO / C3 in Python.', a strong interview answer should define the mechanism, name the common failure mode, and explain the production decision it affects.

    MRO matters when using mixins. Good mixins should be small, documented, and cooperative; otherwise method names collide or parent methods are skipped unexpectedly. |

    Permalink

  22. Explain __name__ == '__main__' in Python.
  23. When do you use the `asyncio` module/package?
  24. When do you use the `logging` module/package?
  25. When do you use the `unittest / pytest` module/package?
  26. When do you use the `venv` module/package?
  27. Python packaging: virtualenv why?
  28. Backend Python interview: explain REST API design.
  29. Backend Python interview: explain migrations.
  30. How does asyncio work internally: event loop, coroutines, tasks and futures?
  31. Which pytest features do you use most?
  32. Explain typing / type hints in Python.
  33. Explain exceptions hierarchy in Python.
  34. When do you use the `pathlib` module/package?
  35. When do you use the `collections` module/package?
  36. When do you use the `itertools` module/package?
  37. When do you use the `functools` module/package?
  38. When do you use the `json` module/package?
  39. When do you use the `concurrent.futures` module/package?
  40. When do you use the `secrets` module/package?
  41. Python packaging: requirements.txt vs pyproject.toml?
  42. Python packaging: dependency pinning?
  43. Backend Python interview: explain FastAPI / Starlette.
  44. Backend Python interview: explain Django ORM vs SQLAlchemy.
  45. Backend Python interview: explain connection pooling.
  46. Backend Python interview: explain caching strategies.
  47. Backend Python interview: explain JWT pitfalls.
  48. Backend Python interview: explain idempotent APIs.
  49. Backend Python interview: explain background jobs.
  50. Backend Python interview: explain observability.
  51. Backend Python interview: explain 12-factor config.
  52. What is free-threaded Python (PEP 703) and how does it change the GIL story?
  53. How do cancellation and timeouts work in asyncio?
  54. What are exception groups and `except*` (Python 3.11)?
  55. What does the Python 3.12 generic syntax (PEP 695) look like, and how do `TypeVar`, `ParamSpec` and `Self` fit in?
  56. When do you use `TypedDict`, `Literal`, `Protocol` and `@overload`?
  57. Compare dataclasses, attrs and Pydantic models.
  58. Explain the iterator protocol and the difference between iterables and iterators.
  59. What are metaclasses, and when is `__init_subclass__` a simpler alternative?
  60. What's the difference between `__new__` and `__init__`?
  61. How does CPython manage memory?
  62. How do you profile and optimize Python code?
  63. What does a modern Python toolchain look like?
  64. What's the difference between `str` and `bytes`, and how do you handle encodings?
  65. Why is `pickle` dangerous, and what should you use instead?
  66. What is the walrus operator (`:=`) and when is it useful?
  67. What is the difference between WSGI and ASGI, and how does it affect how a Python web app handles concurrent requests?
  68. Explain slots in Python.
  69. Explain ABC / Protocol in Python.
  70. Explain property / descriptor in Python.
  71. When do you use the `argparse` module/package?
  72. When do you use the `dataclasses.asdict` module/package?
  73. When do you use the `enum` module/package?
  74. When do you use the `hashlib` module/package?
  75. Python packaging: semantic versioning?
  76. Python packaging: wheels vs sdist?
  77. Python packaging: editable installs?
  78. Python packaging: entry points / scripts?
  79. Backend Python interview: explain rate limiting.
  80. How do you mock correctly in Python tests?
  81. How do you handle dates and time zones correctly in Python?
  82. Why can floating-point math surprise you, and when should you use `Decimal` or `Fraction`?
  83. How do `functools.cache`, `lru_cache` and `cached_property` work, and what are the pitfalls?
  84. How do you run external commands safely with `subprocess`?
  85. What notable improvements came in Python 3.11 through 3.14?
  86. What are template strings (t-strings) in Python 3.14?
  87. How did annotation evaluation change in Python 3.14?
  88. How do sorting, `heapq` and `bisect` help with common algorithmic tasks?
  89. What are weak references in Python and when do you use them?
  90. Which `contextlib` utilities are worth knowing?
  91. How do classic design patterns look in idiomatic Python?
  92. What are the pitfalls of `multiprocessing`?
  93. How do descriptors power properties, methods and ORMs?
  94. How do you implement structured logging in Python services?
  95. What are common security pitfalls in Python applications?
  96. What do `send()`, `throw()`, `close()` and `yield from` do with generators?
  97. Compare f-strings, `str.format` and `%` formatting.
  98. Which built-ins make Python loops cleaner?
  99. What goes into a modern `pyproject.toml`?
  100. How do Django, Flask and FastAPI compare for a new backend project?
  101. What are subinterpreters in Python 3.14?
  102. Python packaging: namespace packages?
  103. What is the difference between a list and a tuple in Python?
  104. How does Python's garbage collection work?