Q1. What is the difference between a list, tuple, and set in Python?
Short answer: List = mutable ordered; tuple = immutable ordered; set = mutable unordered unique.
Strong answer: Lists are mutable and ordered (dynamic arrays). Tuples are immutable, hashable if their contents are, and useful as dict keys or fixed records. Sets store unique, unhashable-free items with O(1) membership. Choose by mutability, ordering, and lookup needs.
Likely follow-up: Why can a tuple be a dict key but a list cannot?
What the interviewer is checking: Understanding of mutability and hashability.
Common mistake: Thinking tuples are just "read-only lists" with no other purpose.
Q2. Explain the GIL and its impact on concurrency.
Short answer: The GIL lets only one thread execute Python bytecode at a time; it limits CPU-bound threading.
Strong answer: CPython’s Global Interpreter Lock serializes bytecode execution, so threads don’t give true parallelism for CPU-bound work — use multiprocessing or native extensions for that. Threads still help I/O-bound work. Python 3.13+ ships an experimental free-threaded (no-GIL) build, and 3.14 continues that work.
Likely follow-up: How do you achieve parallelism for CPU-bound tasks today?
What the interviewer is checking: Current, accurate understanding of the GIL and 3.14 direction.
Common mistake: Claiming threads give parallel CPU speedups in standard CPython.
Q3. What are decorators and how do they work?
Short answer: Callables that wrap a function to add behavior, using @syntax.
Strong answer: A decorator takes a function and returns a new function, letting you add cross-cutting behavior (logging, caching, auth) without changing the wrapped code. @decorator is sugar for f = decorator(f). Use functools.wraps to preserve metadata. functools.lru_cache is a common built-in decorator.
Likely follow-up: How would you write a decorator that takes arguments?
What the interviewer is checking: Understanding of first-class functions and closures.
Common mistake: Forgetting functools.wraps and losing the function name/docstring.
Q4. How does Python manage memory and garbage collection?
Short answer: Reference counting plus a cyclic garbage collector.
Strong answer: CPython frees objects when their reference count hits zero, and a generational cyclic collector handles reference cycles. Understanding this helps avoid leaks from lingering references (globals, caches, closures) and explains why del just decrements a count.
Likely follow-up: What creates a reference cycle and how is it collected?
What the interviewer is checking: Depth beyond "Python handles memory for you".
Common mistake: Believing del immediately frees memory.
Q5. What is the difference between deep copy and shallow copy?
Short answer: Shallow copies the container; deep copies nested objects recursively.
Strong answer: copy.copy() creates a new outer object but shares nested references; copy.deepcopy() recursively duplicates everything. Mutating a nested list in a shallow copy affects the original — a classic bug source with nested data structures.
Likely follow-up: When would a shallow copy cause a subtle bug?
What the interviewer is checking: Awareness of reference semantics.
Common mistake: Assuming assignment or slicing fully clones nested data.
Q6. Explain generators and the yield keyword.
Short answer: Generators produce values lazily, one at a time, preserving state between calls.
Strong answer: A function with yield returns a generator that computes values on demand, using constant memory for large or infinite sequences. Great for streaming pipelines and large-file processing. yield from delegates to a sub-generator.
Likely follow-up: How do generators help with a huge file you can’t load into memory?
What the interviewer is checking: Understanding of lazy evaluation and memory efficiency.
Common mistake: Building a full list when a generator would do.
Q7. What are *args and **kwargs?
Short answer: Collect extra positional and keyword arguments respectively.
Strong answer: *args gathers extra positional args into a tuple; **kwargs gathers extra keyword args into a dict. They enable flexible APIs and forwarding arguments to wrapped functions (common in decorators). Order: positional, *args, keyword-only, **kwargs.
Likely follow-up: How do you forward all arguments to another function?
What the interviewer is checking: Comfort with flexible function signatures.
Common mistake: Confusing the two or misordering parameters.
Q8. How do you handle async I/O in Python?
Short answer: asyncio with async/await for cooperative, single-threaded concurrency.
Strong answer: async def defines coroutines; await yields control on I/O so the event loop runs other tasks. It scales I/O-bound workloads (APIs, DB, network) without threads. Use asyncio.gather for concurrency, and avoid blocking calls inside the loop.
Likely follow-up: What happens if you call a blocking function inside an async coroutine?
What the interviewer is checking: Understanding of the event loop model.
Common mistake: Mixing blocking calls into async code and stalling the loop.
Need Proxy Interview Support?
Share your JD on WhatsApp and clear these rounds with a stack expert.
Q9. What is the difference between @staticmethod, @classmethod, and instance methods?
Short answer: Instance methods take self; classmethod takes cls; staticmethod takes neither.
Strong answer: Instance methods operate on an object (self). classmethods receive the class (cls) and are used for alternative constructors or class-level state. staticmethods are namespaced utility functions with no implicit first arg. Choose by what state you need.
Likely follow-up: When is a classmethod the right choice over a staticmethod?
What the interviewer is checking: OOP understanding in Python.
Common mistake: Using staticmethod where a classmethod constructor fits.
Q10. How would you optimize a slow Python data-processing script?
Short answer: Profile first, then vectorize, use better data structures, or move hot paths to C/NumPy.
Strong answer: Measure with cProfile to find real hot spots. Replace Python loops with vectorized NumPy/pandas ops, use sets/dicts for lookups, stream with generators, cache with lru_cache, and consider multiprocessing or native extensions for CPU-bound sections. Don’t optimize blind.
Likely follow-up: Why profile before optimizing?
What the interviewer is checking: Disciplined performance engineering.
Common mistake: Micro-optimizing before profiling.