Master Python interviews with 50+ essential questions on data structures, OOP, decorators, and real-world problem solving.
10 Questions
~30 min read
Lists are mutable (can be modified after creation) and use square brackets []. Tuples are immutable (cannot be changed) and use parentheses (). Tuples are faster, can be used as dictionary keys, and are preferred for fixed collections. Lists are better when you need to modify the collection.
Shallow copy (copy.copy) creates a new object but references nested objects from the original. Deep copy (copy.deepcopy) creates a new object and recursively copies all nested objects. Use deep copy when you need completely independent copies of nested structures; shallow copy when nested objects should be shared.
List comprehension [x for x in range(10)] creates a full list in memory. Generator expression (x for x in range(10)) creates an iterator that yields values on demand. Use list comprehension when you need the full list; use generator expressions for large sequences or when you only need to iterate once.
Decorators are functions that modify the behavior of other functions without changing their code. They use the @decorator syntax. Example use cases: logging, timing, authentication, caching. A decorator takes a function, wraps it with additional functionality, and returns the wrapper. Common built-in decorators: @property, @staticmethod, @classmethod.
*args allows a function to accept any number of positional arguments as a tuple. **kwargs allows any number of keyword arguments as a dictionary. They enable flexible function signatures. Convention: use these names, though any name with * or ** works. Often used in decorators, class inheritance, and wrapper functions.
Generators are functions that use yield instead of return, producing values lazily one at a time. Benefits: memory efficiency (don't load entire sequence into memory), represent infinite sequences, simpler code than implementing iterators. Use for large datasets, streaming data, or when you don't need all values at once.
The GIL is a mutex that protects access to Python objects, preventing multiple threads from executing Python bytecode simultaneously. This limits true parallelism for CPU-bound tasks in CPython. Solutions: use multiprocessing for CPU-bound work, asyncio for I/O-bound work, or consider PyPy or Cython. The GIL doesn't affect I/O operations.
@staticmethod defines a method that doesn't access instance or class state - it's like a regular function in the class namespace. @classmethod receives the class (cls) as first argument and can access/modify class state. Use staticmethod for utility functions, classmethod for factory methods or operations on class attributes.
Duck typing means Python checks an object's methods/attributes rather than its type. "If it walks like a duck and quacks like a duck, it's a duck." This enables polymorphism without inheritance. Example: any object with a __len__ method works with len(). It promotes flexible, reusable code but requires good documentation.
Python uses reference counting as primary memory management - objects are freed when reference count reaches zero. It also has a generational garbage collector to handle circular references. Memory is managed by a private heap. The memory manager handles allocation; you rarely interact with it directly but should avoid circular references and use context managers.