Skip to main content

Amazon Interview Python Interview Questions

Curated Amazon Interview-level Python interview questions for developers targeting amazon interview positions. 117 questions available.

Last updated:

Python Interview Questions & Answers

Skip to Questions

Welcome to our comprehensive collection of Python interview questions and answers. This page contains expertly curated interview questions covering all aspects of Python, from fundamental concepts to advanced topics. Whether you're preparing for an entry-level position or a senior role, you'll find questions tailored to your experience level.

Our Python interview questions are designed to help you:

  • Understand core concepts and best practices in Python
  • Prepare for technical interviews at all experience levels
  • Master both theoretical knowledge and practical application
  • Build confidence for your next Python interview

Each question includes detailed answers and explanations to help you understand not just what the answer is, but why it's correct. We cover topics ranging from basic Python concepts to advanced scenarios that you might encounter in senior-level interviews.

Use the filters below to find questions by difficulty level (Entry, Junior, Mid, Senior, Expert) or focus specifically on code challenges. Each question is carefully crafted to reflect real-world interview scenarios you'll encounter at top tech companies, startups, and MNCs.

Questions

117 questions
Q1:

What are Python's key features?

Entry

Answer

Python features:
• Interpreted, dynamically typed, high-level
• Object-oriented and functional support
• Large standard library and community
• Automatic memory management
• Portable and readable syntax
Quick Summary: Python key features: simple and readable syntax, dynamically typed, interpreted, garbage-collected memory management, extensive standard library, multi-paradigm (OOP, functional, procedural), large ecosystem (pip packages), cross-platform, and strong community. Popular for web (Django, Flask), data science (pandas, numpy), ML/AI, scripting, and automation.
Q2:

What is the difference between Python 2 and Python 3?

Entry

Answer

Key differences:
• print is a function in Python 3
• / returns float in Python 3
• Strings are Unicode by default
• Most libraries support Python 3 only
Quick Summary: Python 2 (EOL 2020): print is a statement, integer division by default, str is bytes, unicode is separate type, range() returns a list. Python 3: print() is a function, true division by default, str is unicode, bytes is separate, range() returns a lazy iterator. Python 3 is the only supported version now - all new code should use Python 3.
Q3:

What are Python data types?

Entry

Answer

Python data types:
• Numeric: int, float, complex
• Sequence: list, tuple, range
• Text: str
• Mapping: dict
• Set: set, frozenset
• Boolean: bool
• NoneType: None
Quick Summary: Python built-in data types: int, float, complex (numbers), str (text), bool (True/False), list (mutable ordered sequence), tuple (immutable ordered sequence), dict (key-value mapping), set (unique unordered elements), frozenset (immutable set), bytes, bytearray, NoneType. Everything in Python is an object including these primitives.
Q4:

Explain Python variable scoping rules.

Entry

Answer

Scopes:
• Local
• Enclosing
• Global
• Built-in
Use global and nonlocal to modify outer variables.
Quick Summary: Python scoping follows LEGB rule: Local (inside function), Enclosing (in outer function for nested functions), Global (module level), Built-in (Python built-ins). Variables are looked up in this order. global keyword declares a variable is from global scope. nonlocal keyword (Python 3) modifies variable from enclosing function scope.
Q5:

How does Python manage memory?

Entry

Answer

Python uses automatic memory management:
• Reference counting
• Garbage collector for circular references
• No manual allocation/deallocation needed.
Quick Summary: Python uses reference counting as primary memory management - each object tracks how many references point to it. When count drops to 0, memory is freed immediately. A cyclic garbage collector handles reference cycles (A references B, B references A). CPython manages memory in pools and arenas via pymalloc. You can force GC with gc.collect() but rarely need to.
Q6:

What are lists, tuples, sets, and dictionaries?

Entry

Answer

List: ordered, mutable
Tuple: ordered, immutable
Set: unique elements, unordered
Dictionary: key-value pairs, mutable
Quick Summary: List: mutable, ordered, allows duplicates [1, 2, 3]. Tuple: immutable, ordered, allows duplicates (1, 2, 3) - faster than list, used for fixed data. Set: mutable, unordered, unique elements {1, 2, 3} - O(1) membership test. Dict: mutable, key-value pairs, keys must be hashable {key: value}. Choose based on: mutability, order needs, uniqueness, and lookup pattern.
Q7:

Explain Python functions.

Entry

Answer

Functions use def keyword.
Support default, keyword, and variable-length args.
Support lambdas and decorators.
Functions are first-class objects.
Quick Summary: Python functions are first-class objects - assignable to variables, passable as arguments, returnable from other functions. def defines a function, lambda creates anonymous single-expression functions. Default parameter values, *args (variable positional args), **kwargs (variable keyword args). Closures capture variables from enclosing scope. Nested functions, decorators, and higher-order functions are all supported.
Q8:

What are Python modules and packages?

Entry

Answer

Module: single .py file.
Package: directory with __init__.py.
Provide modularity and namespace management.
Quick Summary: Module: a single .py file. Package: a directory with __init__.py containing multiple modules. Import with import module or from module import name. Python searches sys.path for modules. pip installs third-party packages from PyPI into site-packages. Virtual environments (venv) isolate packages per project. __init__.py can define what the package exposes.
Q9:

Explain Python exception handling.

Entry

Answer

Use try/except/finally/else.
Create custom exceptions by subclassing Exception.
Ensures robust error handling.
Quick Summary: Python exception handling: try block runs code that might fail. except catches specific exceptions (except ValueError) or all exceptions (except Exception). else runs if no exception occurred. finally always runs (cleanup). raise raises an exception manually. Use specific exception types - never bare except: which hides bugs. Create custom exceptions by subclassing Exception.
Q10:

What are Python decorators?

Entry

Answer

Decorators modify functions dynamically.
Use @decorator syntax.
Common for logging, authorization, caching.
Quick Summary: Decorators are functions that wrap another function to add behavior without modifying its code. Applied with @decorator syntax above function definition. Common uses: logging, timing, authentication, caching. A decorator takes a function, returns a new function that calls the original. Use functools.wraps(func) to preserve the wrapped function's name and docstring.
Q11:

How does Python handle file operations?

Entry

Answer

Use open() with modes: r, w, a, rb, wb.
Use with statement for auto cleanup.
Supports read(), write(), seek().
Quick Summary: Python file I/O: open(filename, mode) returns a file object. Modes: "r" (read), "w" (write), "a" (append), "b" (binary), "x" (exclusive create). Use with open(...) as f: (context manager) to automatically close the file even if an exception occurs. Read: f.read(), f.readline(), f.readlines(). Write: f.write(). Use pathlib.Path for modern path handling.
Q12:

Explain Python iterators and generators.

Entry

Answer

Iterator: implements __iter__() and __next__().
Generator: uses yield for lazy evaluation.
Efficient for large datasets.
Quick Summary: Iterator: object with __iter__() and __next__() methods that produces values one at a time. Generator: function using yield that automatically becomes an iterator - pauses at each yield and resumes from there. Generators are lazy (compute on demand, memory efficient). Use generators for large sequences where computing all values upfront would be expensive. Generator expression: (x**2 for x in range(10)).
Q13:

How do Python comprehensions work?

Entry

Answer

List: [x*x for x in range(5)]
Set: {x for x in range(5)}
Dict: {x: x*x}
Fast, concise, readable.
Quick Summary: Comprehensions create collections concisely. List: [expr for item in iterable if condition]. Dict: {k: v for k, v in items}. Set: {expr for item in iterable}. Generator: (expr for item in iterable) - lazy, memory efficient. More readable and often faster than equivalent for loops. Avoid deeply nested comprehensions - they become hard to read.
Q14:

Explain *args and **kwargs.

Entry

Answer

*args: variable positional args.
**kwargs: variable keyword args.
Useful for flexible function definitions.
Quick Summary: *args captures any number of positional arguments as a tuple. def func(*args): receives func(1, 2, 3) as args = (1, 2, 3). **kwargs captures keyword arguments as a dict. def func(**kwargs): receives func(a=1, b=2) as kwargs = {"a": 1, "b": 2}. Order in function signature: positional, *args, keyword-only, **kwargs. Unpacking: func(*mylist) and func(**mydict).
Q15:

What are Python's built-in structures for stacks and queues?

Entry

Answer

Stack: list with append/pop.
Queue: collections.deque.
queue.Queue for thread-safe queues.
Quick Summary: Stack: use a list with .append() (push) and .pop() (pop from end) - O(1). Or collections.deque for thread-safe stack. Queue (FIFO): collections.deque with .append() and .popleft() - O(1) both ends. queue.Queue for thread-safe producer-consumer. PriorityQueue: queue.PriorityQueue or heapq module. Avoid using list.pop(0) for queue - it's O(n).
Q16:

How does Python support OOP?

Entry

Answer

Supports classes, inheritance, polymorphism.
Uses __init__, __str__, __repr__, and super().
Supports multiple inheritance.
Quick Summary: Python supports OOP with classes using class keyword. Features: encapsulation (instance variables and methods), inheritance (class Child(Parent)), polymorphism (method overriding), multiple inheritance (class C(A, B)). Special methods (__init__, __str__, __repr__, __len__) customize behavior. Python is duck-typed - objects are used based on behavior, not type.
Q17:

How does Python handle memory for objects?

Entry

Answer

Uses reference counting.
Circular refs handled by GC.
Immutable objects are interned for performance.
Quick Summary: Python objects live on the heap. Each object has a reference count tracked by CPython. When you assign a = [1,2,3], the list object is created on the heap and "a" is a name binding to it. Multiple names can reference the same object (a = b = [] means a and b point to the same list). Objects are garbage collected when no references remain. Large objects may need explicit gc.collect().
Q18:

How do you manage packages in Python?

Entry

Answer

Use pip to install packages.
Use virtual environments for isolation.
requirements.txt for dependency tracking.
Quick Summary: Package management: pip install packagename installs from PyPI. pip freeze > requirements.txt exports dependencies. pip install -r requirements.txt installs from file. Virtual environments: python -m venv venv creates isolated environment. activate it before installing packages. Poetry and Pipenv are modern alternatives that handle virtual envs and dependencies together. conda for data science environments with binary packages.
Q19:

Explain Python's Global Interpreter Lock (GIL).

Entry

Answer

GIL allows only one thread to execute Python bytecode at a time.
Limits CPU-bound threading.
I/O-bound threads work well.
Multiprocessing bypasses GIL.
Quick Summary: The GIL (Global Interpreter Lock) is a mutex in CPython that allows only one thread to execute Python bytecode at a time. This means CPU-bound multi-threaded code doesn't actually run in parallel. I/O-bound threads still benefit (GIL is released during I/O). For CPU-bound parallelism, use multiprocessing (separate processes, no GIL) or C extensions that release the GIL.
Q20:

What are __init__.py and __main__ used for?

Entry

Answer

__init__.py marks a folder as a package.
__main__ allows a script to run directly using main block.
Quick Summary: __init__.py makes a directory a Python package (can be empty). Controls what gets imported with from package import *. __main__.py lets a package be run directly: python -m mypackage. if __name__ == "__main__": guard runs code only when script is executed directly (not when imported as a module). Essential for making scripts work both as executables and importable modules.
Q21:

Explain Python's multiple inheritance and MRO.

Junior

Answer

Python supports multiple inheritance.
MRO (Method Resolution Order) decides method lookup order.
Uses C3 linearization to avoid ambiguity.
Call C.mro() to check the resolution order.
Quick Summary: Python supports multiple inheritance: class C(A, B). MRO (Method Resolution Order) determines which method to call using C3 linearization algorithm. Check with ClassName.__mro__ or ClassName.mro(). super() follows MRO correctly - critical for cooperative multiple inheritance. Diamond problem is resolved by MRO - each class appears once in the resolution order.
Q22:

What are Python magic or dunder methods?

Junior

Answer

Special methods like __init__, __str__, __repr__, __eq__, __add__.
Used for operator overloading and customizing built-in behavior.
Example: obj1 + obj2 calls obj1.__add__(obj2).
Quick Summary: Dunder (double underscore) methods are special methods that Python calls implicitly. __init__ (construction), __str__ (string representation for print), __repr__ (detailed representation), __len__ (len()), __getitem__ (indexing []), __iter__ (iteration), __eq__ (==), __lt__ (<), __add__ (+), __enter__/__exit__ (with statement), __call__ (callable objects). Implementing them makes your classes work naturally with Python built-ins.
Q23:

What are Python metaclasses?

Junior

Answer

Metaclass is the class of a class.
Defines how classes are created.
Useful for validation, auto-registration, or enforcing patterns.
Custom metaclasses extend type.
Quick Summary: Metaclass is the class of a class - controls how classes are created. Default metaclass is type. Custom metaclass: class MyMeta(type): override __new__ or __init__. Use class MyClass(metaclass=MyMeta). Use cases: ORM field registration (Django models), API validation, singleton enforcement, automatic method registration. Metaclasses are powerful but complex - often a class decorator or __init_subclass__ is simpler.
Q24:

Difference between iterators and iterables.

Junior

Answer

Iterable: implements __iter__().
Iterator: implements __next__().
for-loops use iter() and next() internally.
Quick Summary: Iterable: object you can loop over - has __iter__() returning an iterator. Lists, tuples, strings, dicts are iterables. Iterator: object with __next__() - stateful, remembers position, consumed once. Iterables can create multiple iterators. iter(mylist) creates an iterator from a list. Generators are iterators. For-loop calls iter() then repeatedly calls next() until StopIteration.
Q25:

How do generators improve performance?

Junior

Answer

Generators use yield for lazy evaluation.
Memory-efficient for large datasets.
Useful for pipelines and streaming data.
Quick Summary: Generators use lazy evaluation - values produced one at a time on demand, not all at once. Memory efficient: a generator for 1 million numbers uses constant memory vs a list using millions of bytes. Pipelines: chain generators to process data step-by-step (like Unix pipes). yield pauses execution and returns a value; next() resumes from where it left off. Use for large files, infinite sequences, data pipelines.
Q26:

Explain Python decorators in depth.

Junior

Answer

Decorators modify behavior of functions or classes.
Can be parameterized.
Used for logging, caching, auth, timing.
Use @decorator syntax.
Quick Summary: A decorator wraps a function: def my_decorator(func): def wrapper(*args, **kwargs): # before; result = func(*args, **kwargs); # after; return result; return wrapper. Apply with @my_decorator. Decorators with arguments need an extra level of nesting. Class decorators work on classes. functools.wraps preserves metadata. Built-in decorators: @property, @staticmethod, @classmethod, @functools.lru_cache.
Q27:

How does Python handle closures?

Junior

Answer

Closures capture variables from enclosing scopes.
Used in decorators, factories, callbacks.
inner() retains access to outer() variables even after outer() finishes.
Quick Summary: A closure is a nested function that captures and remembers variables from its enclosing scope even after the outer function returns. The enclosed variables form a "cell" object. Closures are the mechanism behind decorators and factory functions. Variables must be declared nonlocal to be assigned inside a closure. Closures in loops: use default argument (i=i) to capture current value.
Q28:

Explain with statement and context managers.

Junior

Answer

Context managers use __enter__ and __exit__.
Automatically handle resource cleanup.
Used for files, network connections, locks.
Can create custom managers using contextlib.
Quick Summary: The with statement ensures resources are properly acquired and released. A context manager implements __enter__ (called when entering with block - can return a value to as clause) and __exit__ (called on exit - even if exception - handles cleanup). Common examples: open() for files, threading.Lock(), database connections. Create custom context managers with contextlib.contextmanager decorator.
Q29:

How do you perform logging in Python?

Junior

Answer

Use logging module.
Levels: DEBUG, INFO, WARNING, ERROR, CRITICAL.
Supports logging to console, files, remote servers.
Preferred over print() in production.
Quick Summary: Python logging: import logging, use logging.getLogger(__name__) to get a logger. Log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL. Configure with basicConfig or a config dict. Add handlers (StreamHandler for console, FileHandler for file, RotatingFileHandler for log rotation). Use formatters to include timestamp, level, module. Prefer logging over print() in any code beyond simple scripts.
Q30:

How do you handle exceptions and create custom exceptions?

Junior

Answer

Use try/except/finally.
Create custom exceptions by subclassing Exception.
raise MyError("msg").
Ensures clean error handling.
Quick Summary: Handle exceptions: try/except/else/finally blocks. Catch specific exceptions (except ValueError as e). Custom exceptions: class ValidationError(Exception): pass - inherit from Exception or a more specific base. Add custom attributes in __init__. Re-raise with raise (no args) inside except. Exception chaining: raise NewError() from original_error. Always clean up in finally.
Q31:

How do you perform unit testing in Python?

Junior

Answer

Use unittest or pytest frameworks.
Mock dependencies using unittest.mock.
Test functions, classes, and APIs.
Quick Summary: Python unit testing: use unittest (built-in) or pytest (more popular). unittest: subclass TestCase, write test_* methods, use self.assertEqual/assertRaises/etc. pytest: just write functions starting with test_, use assert statements (pytest rewrites them for detailed failures). Fixtures, parametrize, and mocking with unittest.mock. Run with pytest or python -m unittest. Aim for 80%+ coverage.
Q32:

Advanced use of *args and **kwargs.

Junior

Answer

*args passes variable positional args.
**kwargs passes variable keyword args.
Used to forward arguments to other functions.
Common in decorators and wrappers.
Quick Summary: Advanced *args/**kwargs: forwarding arguments to another function (func(*args, **kwargs)), combining with keyword-only args (def f(a, b, *, key_only)), unpacking in function calls (f(*list, **dict)). Keyword-only args (after *): def f(a, *, b) forces b to be passed by keyword. Positional-only args (before /): def f(a, b, /) forces a, b to be positional. Both together for fine-grained API control.
Q33:

Explain Python's itertools module.

Junior

Answer

Provides fast, memory-efficient iterators.
Functions: count(), cycle(), combinations(), product().
Useful for looping, combinatorics, pipelines.
Quick Summary: itertools provides efficient iterator building blocks. chain() combines multiple iterables. cycle() repeats infinitely. islice() slices iterators. groupby() groups consecutive elements. product() computes Cartesian product. permutations() and combinations(). count() infinite counter. dropwhile()/takewhile() conditional iterators. All are lazy (memory efficient). Used heavily in data processing pipelines.
Q34:

Explain functools and lru_cache.

Junior

Answer

functools offers higher-order tools.
lru_cache caches results of expensive functions.
Improves performance for recursive or repeated calculations.
Quick Summary: functools module for higher-order functions. lru_cache (Least Recently Used) memoizes a function - caches results keyed by arguments. @lru_cache(maxsize=128) or @cache (Python 3.9, unlimited). Perfect for recursive algorithms (fibonacci) or expensive computations called repeatedly with same inputs. partial() creates new function with pre-filled arguments. reduce() applies function cumulatively.
Q35:

How do you handle file operations with context managers?

Junior

Answer

Use with open("file") for auto-close.
Supports read(), write(), binary modes.
Prevents file descriptor leaks.
Quick Summary: Context managers for file operations: with open("file.txt", "r") as f: data = f.read(). File closes automatically even if an exception occurs. Process files line-by-line to save memory: for line in f: process(line). Use pathlib.Path for modern file path manipulation: Path("dir") / "file.txt". Read CSV with csv module, JSON with json module. Write binary with "wb" mode.
Q36:

How do you connect Python with databases?

Junior

Answer

Use sqlite3, psycopg2, PyMySQL, or ORMs like SQLAlchemy.
Use parameterized queries to prevent SQL injection.
Quick Summary: Python database access: SQLite built-in (sqlite3 module). PostgreSQL/MySQL via psycopg2 or PyMySQL. ORMs: SQLAlchemy (most powerful, any DB) or Django ORM (built into Django). Use parameterized queries to prevent SQL injection (cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))). Always use context managers or try/finally to close connections.
Q37:

How do you implement serialization and deserialization?

Junior

Answer

Use json.dumps()/json.loads().
pickle for Python object serialization.
Avoid untrusted pickle data for security.
Quick Summary: Serialization: convert Python objects to a format for storage or transmission. json module for JSON (human-readable, web-friendly). pickle module for Python-specific binary serialization (any Python object). marshal for Python bytecode. Third-party: marshmallow (validation + serialization), dataclasses with asdict(). Caution: never unpickle data from untrusted sources (security risk).
Q38:

Explain Python's datetime and time modules.

Junior

Answer

datetime provides date/time objects and timedelta.
time handles timestamps and sleep.
Supports formatting and parsing with strptime().
Quick Summary: datetime module: datetime.datetime for date+time, date for date-only, time for time-only, timedelta for durations. strftime(format) converts datetime to string. strptime(string, format) parses string to datetime. Use timezone-aware datetimes: datetime.now(timezone.utc). Python 3.9+ has zoneinfo for IANA timezone support. dateutil library simplifies parsing and timezone handling.
Q39:

How do you implement caching in Python?

Junior

Answer

Use lru_cache or dictionaries for in-memory caching.
Use Redis/Memcached for distributed caching.
Improves performance of repeated calls.
Quick Summary: Caching in Python: functools.lru_cache for in-memory function result caching. dict for simple key-value caching. cachetools library for LRU, TTL, and other cache types. Redis (via redis-py) for distributed caching across processes. Django/Flask caching backends (memcached, Redis). Cache invalidation strategy: TTL-based expiry, event-based invalidation, or versioned cache keys.
Q40:

How do you profile and optimize Python code?

Junior

Answer

Use cProfile or timeit.
Use line profiling for detailed analysis.
Optimize loops, data structures.
Use NumPy or Cython for heavy computation.
Quick Summary: Python profiling tools: cProfile (built-in, function-level timing - python -m cProfile script.py). profile module (pure Python, slower). line_profiler (@profile decorator, line-by-line timing). memory_profiler (memory usage per line). py-spy (sampling profiler, low overhead, production-safe). timeit for benchmarking small code snippets. Always profile before optimizing - don't guess bottlenecks.
Q41:

What are Python descriptors and how are they used?

Mid

Answer

Descriptors define __get__, __set__, and __delete__ methods.
Used for managing attribute access, validation, computed attributes, and reusable logic.
They power @property functionality in Python.
Quick Summary: Descriptors implement __get__, __set__, __delete__ to control attribute access on a class. Used when an attribute needs validation or computation on access. @property is a built-in descriptor. Custom descriptors: class Validator: def __set__(self, obj, value): validate(value); obj.__dict__[name] = value. Used by SQLAlchemy and Django ORM to define column types and relationships.
Q42:

What is __slots__ in Python and why use it?

Mid

Answer

__slots__ restricts dynamic attribute creation.
Saves memory by preventing per-instance __dict__.
Useful for memory-sensitive applications or many small objects.
Quick Summary: __slots__ declares a fixed set of attributes for a class, replacing the per-instance __dict__. Benefits: lower memory usage (no dict overhead per instance), slightly faster attribute access, prevents dynamic attribute creation. Use when creating many instances of a small class. Downside: less flexible, can't add new attributes dynamically, inheritance with slots requires care.
Q43:

Explain Python metaclasses and use cases.

Mid

Answer

Metaclasses control class creation.
Used for validation, enforcing interfaces, singletons, auto-registration.
Defined by extending type and overriding __new__.
Quick Summary: Metaclass controls class creation. type is the default metaclass. Custom metaclass: class Meta(type): def __new__(mcs, name, bases, attrs): modify attrs, return super().__new__(...). Use cases: auto-register subclasses (plugin systems), validate class definition, add methods automatically (ORMs), enforce coding standards. __init_subclass__ (Python 3.6+) is simpler for most use cases.
Q44:

How does Python handle threading and concurrency?

Mid

Answer

threading handles I/O-bound tasks.
GIL limits CPU-bound threads.
multiprocessing enables true parallelism.
concurrent.futures simplifies thread/process pool usage.
Quick Summary: Python threading: threads share memory, good for I/O-bound tasks (network, file I/O). GIL prevents true CPU parallelism. threading.Thread, Lock, RLock, Semaphore, Event, Condition. For CPU-bound tasks use multiprocessing (separate processes, no GIL). concurrent.futures.ThreadPoolExecutor for thread pool. AsyncIO for high-concurrency I/O without threads (event loop, single thread, cooperative multitasking).
Q45:

How do you implement asynchronous programming in Python?

Mid

Answer

Use async/await with asyncio.
async def defines async functions.
await pauses execution.
Ideal for I/O-bound workloads like network or DB operations.
Quick Summary: asyncio enables async programming with a single thread and event loop. async def defines a coroutine. await suspends the coroutine while waiting for I/O (doesn't block the thread - other coroutines run). asyncio.run() starts the event loop. asyncio.gather() runs coroutines concurrently. Use for: many concurrent I/O operations (HTTP, DB, websockets) with far fewer threads than traditional threading.
Q46:

How do Python coroutines work?

Mid

Answer

Coroutines defined with async def.
Execution suspends at await points.
Useful for pipelines, cooperative multitasking, and event-driven systems.
Quick Summary: Coroutines are functions defined with async def that can suspend at await points. When a coroutine awaits something (asyncio.sleep, aiohttp request), control returns to the event loop which runs other coroutines. Unlike threads, coroutines switch cooperatively (at await) not preemptively. This enables thousands of concurrent operations with minimal memory compared to threads.
Q47:

How do you implement concurrent futures for parallel tasks?

Mid

Answer

Use ThreadPoolExecutor or ProcessPoolExecutor.
submit() runs tasks asynchronously.
Retrieve results using result() or as_completed().
Quick Summary: concurrent.futures provides a high-level interface for parallel tasks. ThreadPoolExecutor for I/O-bound parallel tasks. ProcessPoolExecutor for CPU-bound parallel tasks (bypasses GIL with separate processes). Submit tasks with executor.submit(fn, args) returns Future. executor.map(fn, iterable) for parallel map. Use with context manager: with ThreadPoolExecutor(max_workers=4) as executor:.
Q48:

How does Python handle sockets and networking?

Mid

Answer

socket module supports TCP/UDP networking.
Used for client-server communication.
asyncio supports asynchronous networking for high concurrency.
Quick Summary: Python socket programming: socket.socket(AF_INET, SOCK_STREAM) for TCP. bind(), listen(), accept() for server. connect() for client. send() and recv() for data transfer. Use selectors module for non-blocking I/O. asyncio has async socket support. High-level: use requests (HTTP), websockets library, or Twisted for network protocols. Raw sockets rarely needed - use appropriate high-level library.
Q49:

How do you make HTTP requests in Python?

Mid

Answer

Use requests for synchronous HTTP calls.
Use aiohttp or httpx for asynchronous requests.
Supports headers, auth, JSON, and streaming.
Quick Summary: HTTP requests in Python: requests library (simplest, synchronous). response = requests.get(url, headers={}, params={}, timeout=5). POST: requests.post(url, json=data). Session for connection pooling. For async HTTP: aiohttp or httpx. Always set timeouts. Handle errors with response.raise_for_status(). Use sessions for multiple requests to the same host (connection reuse).
Q50:

What are Python design patterns?

Mid

Answer

Patterns include Singleton, Factory, Observer, Strategy, Decorator.
Improve maintainability, structure, and scalability.
Quick Summary: Python design patterns: Singleton (one instance - use module-level variable or metaclass), Factory (create objects without specifying exact class), Observer (publish-subscribe with callbacks), Strategy (swap algorithms - pass functions), Decorator (functools.wraps), Command (encapsulate actions as objects). Python's duck typing and first-class functions make many patterns simpler than in Java/C++.
Q51:

How do Python weak references work?

Mid

Answer

weakref allows referencing objects without preventing GC.
Useful for caching and avoiding memory leaks.
Quick Summary: Weak references (weakref module) hold references to objects without preventing garbage collection. When the referenced object has no strong references left, it's collected even if a weak reference exists. weakref.ref(obj) creates one. weakref.WeakValueDictionary caches objects without preventing GC. Use for: caches that should release memory under pressure, observer patterns without strong coupling.
Q52:

How do you handle file and directory operations?

Mid

Answer

Use os and pathlib for creating, deleting, and navigating files/directories.
Use shutil for copy/move/archive operations.
Quick Summary: pathlib.Path is the modern way: Path("dir") / "file.txt" for path joining. path.exists(), path.is_file(), path.is_dir(). path.mkdir(parents=True, exist_ok=True). path.glob("*.txt") for file search. shutil.copy(), shutil.move(), shutil.rmtree() for file operations. os.walk() or Path.rglob() for directory traversal. Prefer pathlib over os.path for cleaner code.
Q53:

How do you serialize and deserialize custom Python objects?

Mid

Answer

Use json.dumps() with custom default handlers.
pickle supports full object serialization.
Avoid untrusted pickle data for security.
Quick Summary: Custom object serialization: implement __getstate__ and __setstate__ for pickle (control what's pickled). For JSON: implement a custom JSONEncoder subclass with default() method, or convert to dict before json.dumps(). dataclasses.asdict() for dataclasses. marshmallow Schema for validation + serialization. attrs library with converters. Keep serialized format stable for versioned data.
Q54:

How do you profile Python code?

Mid

Answer

Use cProfile, profile, or timeit.
Use line_profiler for detailed bottleneck analysis.
Optimize slow loops and hotspots.
Quick Summary: Python profiling: cProfile for production profiling (low overhead). line_profiler for line-by-line: decorate with @profile, run with kernprof -l. memory_profiler for memory: decorate with @profile, run with python -m memory_profiler. py-spy for sampling production processes (no code changes needed). Visualize cProfile results with snakeviz. Profile, find the bottleneck, optimize, measure again.
Q55:

How do you implement caching in advanced scenarios?

Mid

Answer

Use lru_cache for memoization.
Use Redis or Memcached for distributed caching.
Support TTL and size-based eviction.
Quick Summary: Advanced caching: TTL cache (cachetools.TTLCache) expires entries after N seconds. LRU cache (functools.lru_cache, cachetools.LRUCache) evicts least-recently-used. Redis for distributed caching across processes/servers. Cache-aside: check cache, miss -> load from DB -> store in cache. Stampede prevention: probabilistic early expiry or Redis locking during cache population.
Q56:

How do you handle logging in distributed Python applications?

Mid

Answer

Use structured JSON logging.
Forward logs to ELK, Fluentd, or centralized servers.
Include correlation IDs for traceability.
Quick Summary: Distributed logging: use structured logging (JSON format) so logs are parseable. Include trace/correlation IDs to link log entries across services. Centralize logs with ELK stack or cloud logging. Use logging.handlers.SysLogHandler to forward to syslog. python-json-logger library for JSON output. In async code, pass context via contextvars to ensure correlation IDs are included in all log entries.
Q57:

How do you implement custom context managers?

Mid

Answer

Define __enter__ and __exit__ methods.
Or use contextlib for simplified managers.
Ensures proper cleanup of resources.
Quick Summary: Custom context managers: class-based: implement __enter__ and __exit__. __exit__ receives exception info (exc_type, exc_val, exc_tb) and can suppress exceptions by returning True. Function-based (simpler): use @contextlib.contextmanager decorator, yield once (code before yield = __enter__, after yield = __exit__). contextlib.ExitStack manages multiple context managers dynamically.
Q58:

How do you implement async iterators and async generators?

Mid

Answer

Async generator uses async def with yield.
Async iterator defines __aiter__ and __anext__.
Useful for streaming async data.
Quick Summary: Async iterators implement __aiter__ and __anext__ (async def). Async generators use yield inside async def functions. Consume with async for. Use case: stream data from an async source (websocket, database cursor) without blocking. Example: async def stream_data(): async for row in db.cursor.fetch(): yield row. asyncio.Queue works well with async generators for producer-consumer.
Q59:

What are the main libraries for data analysis in Python?

Mid

Answer

NumPy for numerical computation,
pandas for DataFrame-based manipulation,
SciPy for scientific computing,
Matplotlib and Seaborn for visualization.
Quick Summary: Python data analysis libraries: NumPy (numerical computing, arrays), pandas (data manipulation, DataFrames), SciPy (scientific computing), statsmodels (statistical models). Data viz: matplotlib, seaborn, plotly. Machine learning: scikit-learn, XGBoost, LightGBM. Deep learning: TensorFlow, PyTorch. Jupyter notebooks for interactive exploration. These form the Python data science ecosystem.
Q60:

What is NumPy and why is it important?

Mid

Answer

NumPy provides multi-dimensional arrays and vectorized operations.
Allows fast computation and broadcasting.
Foundation for scientific and ML libraries.
Quick Summary: NumPy provides N-dimensional arrays (ndarray) with vectorized operations - much faster than Python lists. Operations apply to entire arrays without Python loops (C-level speed). Broadcasting: arrays with different shapes can operate together. Key operations: array creation, indexing/slicing, math operations, linear algebra (linalg), FFT, random numbers. Foundation for pandas, scikit-learn, and PyTorch.
Q61:

What is pandas and how is it used?

Mid

Answer

pandas offers Series and DataFrame structures.
Supports filtering, grouping, merging, reshaping.
Ideal for cleaning and preprocessing data.
Quick Summary: pandas provides DataFrame (2D table) and Series (1D column) data structures. Key operations: read_csv/read_excel, select columns (df["col"]), filter rows (df[df.age > 18]), groupby(), merge() for SQL-like joins, pivot_table(), apply() for custom transformations, fillna() for missing data. Use vectorized operations (not loops) for performance. iloc for integer-based, loc for label-based indexing.
Q62:

What are Python data visualization tools?

Mid

Answer

Matplotlib for low-level charts,
Seaborn for statistical visualizations,
Plotly/Bokeh for interactive plots.
Quick Summary: Python data viz: matplotlib (low-level, flexible, foundation of others). seaborn (statistical plots on top of matplotlib, beautiful defaults). plotly (interactive charts, works in Jupyter and web). Altair (declarative, grammar of graphics). bokeh (interactive web plots). In Jupyter: %matplotlib inline. For production dashboards: Dash (plotly) or Streamlit. Choose matplotlib for static, plotly for interactive.
Q63:

How do you handle missing data in pandas?

Mid

Answer

Identify missing values with isnull/notnull.
Fill with mean/median/mode or custom values.
Drop rows or columns when appropriate.
Quick Summary: Handle missing data in pandas: detect with df.isna() or df.isnull(). Drop: df.dropna(axis=0) rows, dropna(axis=1) columns, dropna(subset=["col"]). Fill: df.fillna(value), fillna(df.mean()), fillna(method="ffill") forward fill, bfill backward fill. Interpolate: df.interpolate(). For ML: use SimpleImputer from scikit-learn to fill with mean/median/mode in pipelines.
Q64:

How do you handle categorical data?

Mid

Answer

Convert categories to numeric using encoding.
One-hot for nominal, label encoding for ordinal.
Required for ML algorithms.
Quick Summary: Handle categorical data: pandas Categorical type for memory efficiency. One-hot encoding: pd.get_dummies(df["col"]) or scikit-learn OneHotEncoder. Label encoding: LabelEncoder for ordinal data with natural order. Ordinal encoding: OrdinalEncoder when order matters. Target encoding for high-cardinality categoricals. Always encode test data using fit from training data to prevent data leakage.
Q65:

How do you normalize or standardize data?

Mid

Answer

Normalization scales values to 0–1.
Standardization gives mean 0 and std 1.
Ensures equal feature contribution.
Quick Summary: Normalization scales to [0,1]: (x - min)/(max - min) with MinMaxScaler. Standardization scales to mean=0, std=1: (x - mean)/std with StandardScaler. Use standardization for algorithms that assume normal distribution (linear regression, SVM, neural nets). Normalization for bounded ranges. Always fit scaler on training data only, then transform test data to prevent data leakage.
Q66:

What is scikit-learn and why is it used?

Mid

Answer

scikit-learn provides ML algorithms,
preprocessing tools,
model evaluation and pipelines.
Quick Summary: scikit-learn provides consistent API for ML: fit(X_train, y_train) trains the model, predict(X_test) makes predictions, score() evaluates. Includes: preprocessing (scalers, encoders), feature selection, dimensionality reduction (PCA), classification, regression, clustering, cross-validation, pipelines. Consistent API makes switching algorithms easy for experimentation.
Q67:

What are common machine learning algorithms in Python?

Mid

Answer

Supervised: Linear/Logistic Regression, SVM, Trees, RF.
Unsupervised: K-means, PCA.
Ensemble: Boosting, Bagging.
Quick Summary: Common ML algorithms in Python: Linear/Logistic Regression (baseline, interpretable). Decision Trees and Random Forest (ensemble, handles non-linearity). Gradient Boosting (XGBoost, LightGBM - usually best for tabular data). SVM for small-medium datasets. K-Means for clustering. Neural networks (PyTorch, TensorFlow) for images and NLP. Start simple, add complexity only when needed.
Q68:

How do you split datasets for training and testing?

Mid

Answer

Divide data into training and test sets.
Optionally add validation set.
Prevents overfitting and checks generalization.
Quick Summary: Split data to evaluate model performance on unseen data. train_test_split(X, y, test_size=0.2, random_state=42) gives 80% train, 20% test. Stratified split for imbalanced classes (stratify=y). Never train on test data. Validation set for hyperparameter tuning (or use cross-validation). Test set is used only once at the very end to report final performance.
Q69:

What are pipelines in machine learning?

Mid

Answer

Combine preprocessing and models into a workflow.
Ensures consistent transformations.
Improves reproducibility.
Quick Summary: Scikit-learn Pipeline chains preprocessing and model into one object: Pipeline(steps=[("scaler", StandardScaler()), ("model", LogisticRegression())]). Benefits: prevents data leakage (fit applies only to training data), easier cross-validation, model serialization includes preprocessing, clean code. Combine with GridSearchCV for hyperparameter tuning across all steps.
Q70:

How do you evaluate machine learning models?

Mid

Answer

Classification: Accuracy, Precision, Recall, F1, AUC.
Regression: MSE, MAE, R2.
Used to compare and select models.
Quick Summary: Model evaluation metrics: Classification: accuracy, precision, recall, F1-score (use when classes imbalanced), ROC-AUC, confusion matrix. Regression: MAE (mean absolute error), MSE, RMSE, R-squared. Use cross_val_score for cross-validated scores. Classification report gives all classification metrics at once. Choose metric based on business impact of false positives vs false negatives.
Q71:

How do you handle overfitting and underfitting?

Mid

Answer

Overfitting: Reduce complexity, regularization, cross-validation.
Underfitting: Increase model complexity or features.
Quick Summary: Overfitting: model learns training data too well, poor on new data. Underfitting: model too simple, poor on both. Fixes for overfitting: more training data, regularization (L1/L2), dropout (neural nets), simpler model, cross-validation. Fixes for underfitting: more features, more complex model, less regularization. Learning curves (train vs validation error vs dataset size) diagnose the problem.
Q72:

How do you save and load machine learning models?

Mid

Answer

Use pickle or joblib for serialization.
Framework-specific save/load for deep learning.
Allows reuse without retraining.
Quick Summary: Save ML models: joblib.dump(model, "model.pkl") and joblib.load() for scikit-learn (handles NumPy arrays efficiently). pickle.dump() works too but joblib is preferred for large models. TensorFlow: model.save("model_dir") - SavedModel format. PyTorch: torch.save(model.state_dict(), "model.pth") and model.load_state_dict(torch.load()). For production: ONNX format for cross-framework deployment.
Q73:

How do you implement feature selection?

Mid

Answer

Use correlation, recursive feature elimination,
or model-based selectors.
Improves performance and reduces dimensionality.
Quick Summary: Feature selection reduces noise and overfitting, speeds training. Methods: filter (correlation, chi-squared, mutual information - no model needed), wrapper (RFE - recursive feature elimination, trains model), embedded (L1 regularization - Lasso sets irrelevant feature weights to 0). SelectKBest, RFECV in scikit-learn. Feature importance from tree models. Start with filter methods for speed.
Q74:

How do you handle time series data?

Mid

Answer

Use datetime indexing, resampling, rolling windows.
Model trends, seasonality.
Use pandas and statsmodels.
Quick Summary: Time series data handling: parse dates with pd.to_datetime(), set DatetimeIndex. Resample: df.resample("1H").mean() for hourly aggregation. Rolling statistics: df.rolling(7).mean() for 7-day moving average. Lag features: df["lag_1"] = df["value"].shift(1). Seasonality and trend decomposition: statsmodels.tsa.seasonal_decompose. Models: ARIMA, Prophet (Facebook), LSTM (deep learning).
Q75:

How do you perform cross-validation?

Mid

Answer

Split data into multiple folds.
Train and test repeatedly.
Ensures robust model evaluation.
Quick Summary: Cross-validation evaluates model performance more reliably than single train/test split. KFold: split data into K folds, train on K-1, test on 1, repeat K times, average scores. StratifiedKFold for classification (preserves class distribution in each fold). cross_val_score(model, X, y, cv=5) does 5-fold CV. Use for: hyperparameter tuning (GridSearchCV uses CV internally), comparing models, reporting performance.
Q76:

What are Python tools for NLP?

Mid

Answer

NLTK for tokenization and parsing.
spaCy for fast NLP pipelines.
Text preprocessing for ML.
Quick Summary: Python NLP tools: NLTK (classical NLP - tokenization, stemming, POS tagging, good for learning). spaCy (production NLP - fast, pre-trained models, named entity recognition). Hugging Face Transformers (BERT, GPT models - state of the art). Gensim (word embeddings - Word2Vec). TextBlob (simple sentiment analysis). Use spaCy for production, Transformers for deep learning NLP tasks.
Q77:

How do you handle large datasets in Python?

Mid

Answer

Use chunking or lazy loading.
Use vectorized NumPy/pandas operations.
Use Dask or PySpark for distributed computing.
Quick Summary: Large dataset handling in Python: pandas chunking: pd.read_csv(file, chunksize=10000) reads in chunks. Dask (parallel pandas on multiple cores or clusters). Polars (Rust-based, much faster than pandas for large files). Vaex (lazy evaluation, out-of-core computation). Parquet format (columnar, compressed) instead of CSV. PySpark for distributed processing at very large scale.
Q78:

How do you deploy Python ML models?

Mid

Answer

Expose models using Flask, FastAPI, or Django.
Containerize with Docker.
Use CI/CD and cloud platforms for production.
Quick Summary: Deploy Python ML models: Flask or FastAPI as REST API wrapper around the model. Serialize model with joblib/pickle, load on startup. Docker container for portability. Kubernetes for scaling. MLflow for experiment tracking and model registry. BentoML or Seldon for ML-specific serving with versioning. Monitor predictions in production (data drift, performance degradation). Batch prediction jobs for non-real-time use cases.
Q79:

What are the main Python web frameworks and their use cases?

Senior

Answer

Flask: Lightweight and flexible, ideal for microservices.
Django: Full-featured framework with ORM, admin, and authentication.
FastAPI: High-performance async API framework.
Pyramid/Tornado: Used for scalable or asynchronous workloads.
Quick Summary: Python web frameworks: Django (full-stack, batteries-included, ORM, admin, auth - for full web apps), Flask (micro-framework, flexible, choose your own components - for APIs and small apps), FastAPI (modern, async, auto-generates OpenAPI docs, Pydantic validation - for high-performance APIs), Tornado (async, websockets). FastAPI is the fastest growing choice for new REST APIs.
Q80:

How does Flask handle routing and requests?

Senior

Answer

Routes map URLs to Python functions.
Decorators define endpoint behavior.
Request/response objects manage headers, parameters, and bodies.
Quick Summary: Flask routing: @app.route("/users/") decorates a function. Supports methods parameter: methods=["GET", "POST"]. URL converters: , , , . request object provides form data, JSON body (request.get_json()), headers, files. Response: return jsonify(data), return render_template(), or return Response object with custom status.
Q81:

How does Django handle URL routing?

Senior

Answer

URL patterns map URLs to views.
Supports dynamic parameters, namespaces, and reverse resolution.
Maintains separation of logic and presentation.
Quick Summary: Django URL routing: define URL patterns in urls.py: path("users//", views.user_detail). Include app URLs in project urls.py: include("users.urls"). Named URLs: path(..., name="user-detail") allows reverse lookup: reverse("user-detail", kwargs={"pk": 1}). Class-based views have as_view(). URL patterns are matched top-to-bottom; first match wins.
Q82:

What is the difference between function-based and class-based views in Django?

Senior

Answer

Function-based views: simple and direct.
Class-based views: reusable patterns, mixins, and structured handling of HTTP methods.
Quick Summary: Function-based views (FBV): simple Python functions receiving request, returning response. Easy to understand, explicit flow. Class-based views (CBV): inherit from generic views (ListView, DetailView, CreateView), less code for standard CRUD operations, mixins for reusability. FBV: better for custom or complex logic. CBV: better for standard CRUD where Django generic views save significant boilerplate.
Q83:

How do Python frameworks handle templates?

Senior

Answer

Templates separate business logic from UI.
Use engines like Jinja2 or Django Template Language.
Support inheritance, loops, conditions, and reusable components.
Quick Summary: Django templates: {{ variable }} for output, {% tag %} for logic ({% if %}, {% for %}). Template inheritance: {% extends "base.html" %} and {% block content %}. Template filters: {{ value|lower|truncatewords:10 }}. Jinja2 is the default in Flask (and optional in Django). FastAPI uses Jinja2. Templates auto-escape HTML to prevent XSS. Always use template engine rather than string concatenation for HTML.
Q84:

How do you handle forms and input validation?

Senior

Answer

Form libraries parse, validate, and sanitize input.
Flask uses WTForms; Django has built-in forms with validation rules.
Protects against invalid and malicious input.
Quick Summary: Django forms: Form class with field types (CharField, EmailField, IntegerField) and validators. is_valid() runs validation. cleaned_data provides sanitized values. ModelForm auto-generates form from a Model. Flask-WTF adds CSRF protection and WTForms to Flask. FastAPI uses Pydantic models for request validation with automatic type coercion and error messages.
Q85:

How do you implement authentication and authorization?

Senior

Answer

Authentication verifies identity; authorization controls access.
Use sessions, JWTs, OAuth, or framework built-ins.
Django provides full authentication system; Flask uses extensions.
Quick Summary: Django auth: built-in User model, login/logout views, @login_required decorator, permission system. JWT for APIs: use djangorestframework-simplejwt. Flask: Flask-Login for session management, Flask-JWT-Extended for JWT. FastAPI: OAuth2PasswordBearer scheme with JWT. Pattern: on login, issue short-lived JWT + refresh token, validate JWT on each request without DB lookup.
Q86:

How do you build REST APIs in Python frameworks?

Senior

Answer

Map CRUD operations to HTTP verbs.
Use serializers for JSON conversion.
Follow REST principles like statelessness, versioning, and proper endpoint design.
Quick Summary: REST APIs in Python: Django REST Framework (DRF) adds serializers, viewsets, routers, authentication to Django. Flask-RESTful or Flask-RESTX for Flask. FastAPI has native REST support with Pydantic models for validation and auto-generated OpenAPI docs. Key concepts: serializers/schemas validate and convert data, viewsets provide CRUD operations, routers generate URL patterns automatically.
Q87:

How do you handle database access with ORM?

Senior

Answer

ORM maps classes to database tables.
Django ORM and SQLAlchemy handle queries, joins, and relationships.
Supports migrations and validation.
Quick Summary: Django ORM: define models as Python classes, create with model.save() or Model.objects.create(). Query: Model.objects.filter(age__gt=18).order_by("name")[:10]. Relationships: ForeignKey, ManyToManyField, OneToOneField. select_related() for JOIN queries (prevents N+1). prefetch_related() for M2M. SQLAlchemy: more flexible, works with any framework, explicit session management.
Q88:

How do you perform database migrations?

Senior

Answer

Migrations track schema changes.
Auto-generated scripts modify tables and fields.
Keep environments consistent across dev, staging, and production.
Quick Summary: Django migrations: python manage.py makemigrations (generates migration files from model changes), python manage.py migrate (applies to DB). Migrations track schema changes in version control. SQLAlchemy uses Alembic for migrations: alembic revision --autogenerate, alembic upgrade head. Always review auto-generated migrations before applying. Back up production DB before running migrations.
Q89:

How do you implement caching in web applications?

Senior

Answer

Caching reduces database load and speeds responses.
Use Redis or Memcached.
Supports page, fragment, and function-level caching.
Quick Summary: Caching in web apps: Django cache framework supports Memcached, Redis, file, database backends. @cache_page(60*15) caches a view response for 15 min. cache.get()/set() for granular caching. Redis is the standard choice (fast, distributed, TTL support). Cache DB query results, expensive computations, session data. Invalidate cache on data changes. CDN caches static files at the edge.
Q90:

How do you implement logging for web applications?

Senior

Answer

Log request context, errors, and performance metrics.
Integrate with monitoring tools.
Helps diagnose issues and maintain observability.
Quick Summary: Web app logging: use Python logging module configured with handlers. Log every request with timing. Log errors with full traceback. Structured logging (JSON) works with centralized log services (ELK, Datadog). In Django: LOGGING setting configures handlers and loggers. gunicorn/uwsgi pass logs to stdout for container environments. Include request ID in all log entries for tracing.
Q91:

How do you secure Python web applications?

Senior

Answer

Mitigate XSS, CSRF, SQL injection, and other attacks.
Use HTTPS, secure cookies, and proper session handling.
Rely on framework security middleware.
Quick Summary: Python web security: CSRF protection (Django includes this, use csrf_token in forms). SQL injection: always use ORM or parameterized queries. XSS: template engines auto-escape (don't use mark_safe() with user input). Authentication: use Django auth or established JWT libraries. HTTPS only. Keep dependencies updated (pip-audit checks for CVEs). Rate limiting on login endpoints. CORS configuration.
Q92:

How do you handle REST API versioning?

Senior

Answer

Use URL-based (/v1/), header-based, or media-type versioning.
Ensures backward compatibility as APIs evolve.
Quick Summary: REST API versioning strategies: URI versioning (/api/v1/, /api/v2/) - most common, visible in URLs. Header versioning (Accept: application/vnd.api.v2+json) - cleaner URLs. Query parameter (?version=2) - easy but pollutes URLs. DRF supports namespace versioning, URL-based versioning. Run old and new versions simultaneously during transition. Deprecate with Sunset header.
Q93:

How do you implement pagination, filtering, and sorting in APIs?

Senior

Answer

Pagination splits large data sets.
Filtering uses query parameters.
Sorting results ensures consistent ordering and performance.
Quick Summary: DRF pagination: PageNumberPagination, LimitOffsetPagination, CursorPagination. Filtering: django-filter library with DjangoFilterBackend. Search: SearchFilter on specific fields. Ordering: OrderingFilter allows clients to sort. FastAPI uses Query parameters with Depends() for pagination. Implement cursor-based pagination for large datasets (stable under insertions) instead of offset-based.
Q94:

How do you test Python web applications?

Senior

Answer

Unit tests for logic, integration tests for endpoints.
Use framework test clients to simulate requests.
Mock external dependencies.
Quick Summary: Python web testing: pytest + pytest-django or pytest-flask. Django TestCase uses a test database (auto-rollback per test). APIClient (DRF) or test_client() for HTTP testing. Mock external services with unittest.mock or responses library. Factory Boy for test data fixtures. Locust or k6 for load testing. Selenium/Playwright for end-to-end browser testing.
Q95:

How do you handle file uploads and downloads?

Senior

Answer

Validate file types and sizes.
Store files securely.
Use streaming for large downloads.
CDNs improve performance.
Quick Summary: File uploads: Django: request.FILES, FileField/ImageField model fields. Validate file size and type. Store: locally (FileSystemStorage), S3 (django-storages with boto3). Flask: request.files, werkzeug.secure_filename() to sanitize filenames. FastAPI: UploadFile type. Always validate MIME type server-side (not just extension). Downloads: StreamingResponse for large files to avoid memory issues.
Q96:

How do you implement middleware in Python frameworks?

Senior

Answer

Middleware intercepts requests and responses.
Used for logging, authentication, caching, error handling.
Stackable for modular behavior.
Quick Summary: Django middleware: MIDDLEWARE list in settings.py. Each middleware is a class with process_request and/or process_response methods. Process order: request goes top-to-bottom, response goes bottom-to-top. Common uses: authentication, CORS headers, request logging, rate limiting, compression. Flask: @app.before_request and @app.after_request decorators for simpler middleware. WSGI middleware wraps the entire application.
Q97:

How do you handle asynchronous tasks in web frameworks?

Senior

Answer

Use Celery or RQ for background tasks.
Async endpoints prevent blocking.
Improves responsiveness for heavy workloads.
Quick Summary: Async tasks in web frameworks: Celery is the standard for background task queues (Redis or RabbitMQ as broker). Django-Q and Huey are lighter alternatives. FastAPI: BackgroundTasks for quick tasks, Celery for heavyweight. Pattern: API returns immediately with a task ID, client polls for result. Use for: email sending, image processing, PDF generation, long-running computations.
Q98:

How do you deploy Python web applications?

Senior

Answer

Use WSGI servers (Gunicorn, uWSGI) or ASGI servers (Uvicorn, Daphne).
Reverse proxy with Nginx.
Containerize with Docker and automate via CI/CD.
Quick Summary: Python web deployment: containerize with Docker (Dockerfile: FROM python, pip install, CMD gunicorn). Run with gunicorn (WSGI) or uvicorn (ASGI). Nginx as reverse proxy and static file server. Docker Compose for local dev with DB. Kubernetes for production scaling. Cloud: AWS Elastic Beanstalk, GCP App Engine, Heroku, Railway. Always use environment variables for config, never hardcode secrets.
Q99:

How do you implement asynchronous programming with asyncio?

Expert

Answer

Asyncio provides an event loop for managing asynchronous tasks.
Enables non-blocking I/O.
Uses coroutines, tasks, and futures for high-performance concurrency.
Quick Summary: asyncio event loop runs coroutines cooperatively. asyncio.run(main()) starts the loop. Create coroutines with async def, await I/O operations. asyncio.gather(*coros) runs coroutines concurrently. asyncio.create_task() schedules a coroutine without awaiting immediately. asyncio.Queue for async producer-consumer. asyncio.timeout() (Python 3.11) for timeouts. Use async libraries: aiohttp, asyncpg, aiobotocore.
Q100:

What are Python coroutines and how are they useful?

Expert

Answer

Coroutines can pause and resume execution.
Ideal for high-latency operations without blocking the thread.
Used in scalable servers and data pipelines.
Quick Summary: Coroutines are async functions (async def) that can pause at await points without blocking. Unlike threads, coroutines cooperatively yield control. They're more memory efficient (no thread stack) and easier to reason about (explicit yield points). Useful for: concurrent API calls, database queries, file I/O where waiting is the bottleneck. Use asyncio.gather() to run multiple coroutines concurrently.
Q101:

How do Python tasks and futures work in concurrency?

Expert

Answer

Tasks schedule coroutines on the event loop.
Futures represent results not yet available.
Useful for coordinating parallel async operations.
Quick Summary: asyncio.Task wraps a coroutine and schedules it on the event loop. task = asyncio.create_task(coro()) runs immediately without awaiting. asyncio.Future is a lower-level promise - set result with future.set_result(). concurrent.futures.Future is the thread/process pool future. await task waits for task completion. task.cancel() cancels the task. asyncio.gather returns results of multiple tasks.
Q102:

How do Python threads differ from processes?

Expert

Answer

Threads share memory and suit I/O-bound tasks.
Processes have separate memory and suit CPU-bound tasks.
Processes bypass GIL for true parallelism.
Quick Summary: Threads: share memory, OS-scheduled, lighter weight than processes, GIL limits CPU parallelism. Processes: separate memory spaces (communicate via queues/pipes/shared memory), true CPU parallelism, higher overhead, more isolation. Use threads for I/O-bound work (network, file), processes for CPU-bound work (computation, data processing). multiprocessing.Pool parallelizes functions across cores.
Q103:

How do you handle synchronization in Python concurrency?

Expert

Answer

Use locks, semaphores, events, and conditions.
Prevent race conditions and ensure safe shared-resource access.
Critical in multi-threaded applications.
Quick Summary: Python concurrency synchronization: threading.Lock for mutual exclusion, RLock for reentrant locking, Semaphore limits concurrent access, Event for thread signaling, Condition for wait/notify. For asyncio: asyncio.Lock, asyncio.Semaphore, asyncio.Event. Queue (queue.Queue or asyncio.Queue) is the safest way to share data between concurrent units - no manual locking needed.
Q104:

What are Python design patterns and their use cases?

Expert

Answer

Singleton, Factory, Observer, Strategy, Decorator.
Provide modularity, scalability, and maintainability.
Applied in complex architecture and large systems.
Quick Summary: Python design patterns: Singleton (module-level instance), Factory (function that returns different types based on input), Strategy (pass different functions/callables), Observer (callbacks list or signal library), Decorator (functools.wraps), Iterator (yield), Context Manager (__enter__/__exit__), Dependency Injection (pass dependencies as arguments). Python's first-class functions simplify many patterns.
Q105:

How do Python descriptors, properties, and slots optimize classes?

Expert

Answer

Descriptors control attribute access.
Properties provide clean getters/setters.
Slots reduce memory by avoiding __dict__.
Useful for high-performance apps.
Quick Summary: Descriptors: implement __get__/__set__/__delete__ for attribute-level control - used for validation and computed properties. @property is the built-in descriptor shortcut. __slots__: replaces per-instance __dict__ with a fixed set of attributes, saves 40-50% memory per instance for classes with many instances. Properties add logic to attribute access without changing the public interface.
Q106:

How do you profile Python applications?

Expert

Answer

Use cProfile, timeit, and line profiling.
Identify slow functions and optimize algorithms.
Apply vectorization and efficient data structures.
Quick Summary: Profile Python applications: cProfile (built-in, minimal overhead): python -m cProfile -o output.prof script.py. Visualize with snakeviz output.prof. For production: py-spy (sampling profiler - attach to running process without code changes). Line-level: kernprof -l -v script.py with @profile decorator. Memory: python -m memory_profiler with @profile. Always profile first, optimize second.
Q107:

How do you optimize memory in Python?

Expert

Answer

Use generators for lazy evaluation.
Reduce object creation.
Use slots, weak references, and optimized structures.
Quick Summary: Python memory optimization: use __slots__ to eliminate per-instance __dict__ overhead. Use generators instead of lists for large sequences. Prefer bytes over str for binary data. Use array module instead of list for homogeneous numeric data. tracemalloc (built-in) traces memory allocations. gc.collect() forces GC. Avoid circular references with weak references. Profile with memory_profiler to find leaks.
Q108:

How do Python weak references help manage memory?

Expert

Answer

Weak references allow referencing objects without preventing GC.
Useful in caching and preventing memory leaks in long-running apps.
Quick Summary: Weak references allow objects to be garbage collected even if a weak reference exists. weakref.ref(obj) creates a weak reference - call it to get the object or None if collected. weakref.WeakValueDictionary: values can be GC'd when no strong references exist (cache that releases memory automatically). WeakKeyDictionary: keys can be collected. Used in caches, memoization, and observer patterns to prevent memory leaks.
Q109:

How do Python context managers improve resource handling?

Expert

Answer

Automatically clean up resources via __enter__ and __exit__.
Prevent leaks for file, DB, and network operations.
Essential for robust resource management.
Quick Summary: Context managers ensure proper resource cleanup. with statement calls __enter__ on entry (can return value via "as"), __exit__ on exit regardless of exceptions. __exit__ receives exception info - return True to suppress the exception. contextlib.contextmanager converts a generator function into a context manager (yield separates enter/exit). contextlib.suppress(Exception) suppresses specific exceptions.
Q110:

How do you handle advanced exception management in Python?

Expert

Answer

Use structured try/except/finally.
Create custom exception hierarchies.
Enable cleaner recovery and better debugging.
Quick Summary: Advanced exception handling: exception chaining (raise NewError() from original keeps cause), suppress context with raise NewError() from None, exception groups (Python 3.11 - handle multiple exceptions from concurrent operations with ExceptionGroup), contextlib.suppress(ErrorType) to silently ignore, custom exception hierarchies for domain errors, logging exceptions with exc_info=True to capture traceback.
Q111:

How do you implement logging for large Python applications?

Expert

Answer

Use structured logging with context.
Supports file, console, and remote handlers.
Enhances monitoring and traceability in production.
Quick Summary: Large app logging: use logging.getLogger(__name__) in each module (hierarchical). Configure root logger once at startup. Structured logging with python-json-logger for machine-readable output. Handlers: RotatingFileHandler (size-based rotation), TimedRotatingFileHandler (daily rotation). Send to centralized logging: ELK, Datadog, CloudWatch. Add request context (user, trace ID) using logging.Filter.
Q112:

How do you handle multiprocessing and parallelism efficiently?

Expert

Answer

Use ProcessPoolExecutor for CPU-bound tasks.
Distribute workloads across processes.
Avoid shared state unless using managers or queues.
Quick Summary: Python multiprocessing: multiprocessing.Pool for parallel task execution across CPU cores. pool.map(func, iterable) for parallel map. pool.starmap() for multiple arguments. ProcessPoolExecutor (concurrent.futures) is a cleaner API. Share data with multiprocessing.Queue, Pipe, or shared memory (multiprocessing.shared_memory in Python 3.8+). Spawn vs fork: spawn is safer on macOS/Windows (default), fork is faster on Linux.
Q113:

How do you implement caching in advanced Python applications?

Expert

Answer

Use in-memory or distributed caches like Redis.
Apply eviction strategies and TTL policies.
Boosts performance for repeated computations.
Quick Summary: Advanced Python caching: functools.cache (Python 3.9, unlimited LRU). cachetools.LRUCache(maxsize=100), TTLCache(maxsize=100, ttl=300). Redis for distributed caching: cache.set(key, json.dumps(value), ex=300). Django cache framework with RedisCache backend. For ML: cache expensive model predictions. Cache stampede prevention: probabilistic early expiration or Redis SET NX lock during cache population.
Q114:

How do you debug and trace Python applications?

Expert

Answer

Use debuggers, logs, and profiling.
Trace executions to find runtime issues.
Unit tests help detect early failures.
Quick Summary: Python debugging and tracing: pdb (built-in debugger) - import pdb; pdb.set_trace() or breakpoint() (Python 3.7+). VS Code and PyCharm have visual debuggers. logging.debug() for production-safe tracing. sys.settrace() for custom tracing. traceback module for exception details. faulthandler for crash diagnostics. Python 3.12+ improved error messages and tracebacks for better debugging.
Q115:

How are configuration and environment variables managed in Python?

Expert

Answer

Use env variables, config files, or libraries.
Keep secrets secure.
Supports portability across environments.
Quick Summary: Config management in Python: os.environ for environment variables. python-dotenv loads .env files into os.environ. pydantic Settings class with env_prefix for typed config with validation. dynaconf for multiple environments. 12-factor app principle: config in environment, not code. Never hardcode secrets - use environment variables or a secrets manager (AWS Secrets Manager, Vault). Different .env files per environment.
Q116:

How do you handle concurrency in Python web frameworks?

Expert

Answer

Async frameworks enable non-blocking requests.
Background workers handle long tasks.
Improves scalability and responsiveness.
Quick Summary: Async web frameworks: FastAPI and Starlette use asyncio natively - define route handlers as async def for non-blocking I/O. Django 3.1+ supports async views and middleware. Use async DB libraries: asyncpg (PostgreSQL), motor (MongoDB), aioredis. Don't mix sync and async code carelessly - sync calls block the event loop. Use asyncio.to_thread() to run blocking code in a thread pool without blocking.
Q117:

How do you integrate Python with external libraries efficiently?

Expert

Answer

Use standard APIs and dependency management.
Ensure compatibility and maintainability.
Supports performant, modular architectures.
Quick Summary: Integrating Python with external libraries: pip install and import. C extensions: ctypes and cffi for calling C libraries directly. Cython compiles Python to C for performance. numpy provides C interop via the buffer protocol. Use subprocess for system commands. For Java interop: Py4J or Jython. For Rust: PyO3 bindings. Wrap external libraries with Python classes to provide a Pythonic interface.

Curated Sets for Python

No curated sets yet. Group questions into collections from the admin panel to feature them here.

Ready to level up? Start Practice