Language Fundamentals & Execution Model
What does the if __name__ == '__main__' idiom do, and why is it used?
Is Python a compiled or interpreted language? Explain the role of .pyc files and the Python Virtual Machine (PVM).
What is your favorite feature introduced in a recent Python version (3.12 or 3.13), and how does it solve a problem that existed in older versions?
What are the major differences between Python 2 and Python 3 that you should be aware of?
What happens at the bytecode level when a Python script is executed?
How does the 'Specializing Adaptive Interpreter' introduced in 3.11/3.12 improve performance?
Variables Scope & Object References
What is the fundamental difference between the is operator and the == operator in terms of memory and the data model?
Explain the LEGB rule. What happens to the scope when you use the global or nonlocal keywords inside a nested function?
What happens if you use a mutable object like a list or dictionary as a default argument in a function, and why is this considered a gotcha?
What is a closure in Python, and how does the interpreter 'remember' the values of the enclosing scope even after the outer function has finished executing?
Is Python 'call-by-value' or 'call-by-reference'? Explain the concept of 'call-by-object-reference' (or 'assignment').
What is string and integer interning in Python, and why does a=256;b=256;a is b return True while a=257;b=257;a is b might return False?
Built In Data Structures
What is the difference between a list, a tuple, a set, and a dictionary, and when would you choose each?
What is a namedtuple, and how does it compare to a regular tuple or a class?
How do Python's collections.deque and list differ in terms of time complexity for common operations?
What requirements must an object meet to be used as a key in a Python dictionary, and how does Python handle hash collisions?
What is a frozenset, and how does it differ from a regular set?
Are Python dictionaries ordered? Explain the insertion-order guarantee introduced in Python 3.7.
What are defaultdict, Counter, and OrderedDict in the collections module, and when would you use them?
Beyond mutability, what are the architectural differences between a list and a tuple, and why is a tuple slightly more memory-efficient?
Exception Handling
What is the purpose of the else and finally clauses in a try/except block?
Explain the 'Easier to Ask for Forgiveness than Permission' (EAFP) coding style. Why is it often preferred in Python over 'Look Before You Leap' (LBYL)?
Why is it considered bad practice to use except Exception? Explain the Python exception hierarchy and where BaseException fits in.
What is duck typing, and how does it differ from EAFP?
How do you define a custom exception, and what are the best practices for exception hierarchies?
What is exception chaining, and what does 'raise ... from ...' do?
Object Oriented Programming
What is the difference between a classmethod, a staticmethod, and a regular instance method?
What is the difference between __str__ and __repr__, and when is each used?
What is an Enum in Python, and why would you use one instead of plain constants?
What are the advantages of using @dataclass over a regular class or a namedtuple, and how does it handle default values and mutability?
How do Python's 'dunder' (magic) methods allow for operator overloading and protocol implementation?
What is the relationship between __eq__ and __hash__, and what happens if you override one but not the other?
What is the __call__ method, and how does it let you make instances of a class callable?
How does Python determine the truthiness of an object, and what role do __bool__ and __len__ play?
When would you use __slots__ in a class definition, and what are the trade-offs regarding memory and flexibility?
Explain the difference between __init__ and __new__. When would you specifically need to override __new__?
Explain the difference between __getattr__ and __getattribute__.
Inheritance Metaclasses & Descriptors
What is the purpose of the abc module, and how does it help enforce an interface compared to standard inheritance?
How does Python handle multiple inheritance? Explain the C3 Linearization algorithm and how super() determines which class to call next.
Explain how the Descriptor protocol works. How do @property, @classmethod, and @staticmethod use descriptors under the hood?
What is a metaclass, and how does it differ from a standard class? When would you use a metaclass instead of a class decorator?
When would you use __init_subclass__ instead of a metaclass?
Type Hints & Duck Typing
What is the purpose of the typing module? Does Python enforce these types at runtime, and if not, why are they used in modern production codebases?
How does Python's 'Duck Typing' philosophy differ from 'Strong Typing'?
Why would you use typing.Annotated?
What is the difference between Final and ClassVar in type hinting?
What is 'Duck Typing', and how does it influence the way you design interfaces in Python compared to a strictly typed language like Java?
Explain the difference between Nominal typing and Structural typing (Protocols) in Python.
What is the difference between typing.Any and object in a type hint?
Explain the new Type Parameter Syntax introduced in PEP 695 (Python 3.12).
Memory Management & Garbage Collection
How does Python's memory management work? Explain the difference between reference counting and the cyclic garbage collector, and how Python handles two objects that reference each other.
What is the difference between the stack and the heap in the context of Python's memory management, and who manages the private heap?
What are 'Immortal Objects' (PEP 683) and how do they help with multi-processing performance?
Why does Python not immediately release memory back to the operating system when an object is deleted?
How does generational garbage collection work in Python, and why does the collector move objects between 'Generation 0', '1', and '2'?
Iterators Generators & Coroutines
What is the difference between a generator and a list? Why are generators considered 'lazy'?
What are the memory benefits of using a generator expression over a list comprehension when processing a very large file?
What is the difference between an iterable, an iterator, and a generator? What are the memory implications of using a generator over a list comprehension?
How does the yield keyword work, and what is the difference between yield and yield from?
What is the difference between an Iterator and an Iterable? How do you implement the Iterator protocol?
What is the difference between a Coroutine and a standard Generator?
What do coroutines and generators have in common, and how did generators evolve into async/await?
What do the send(), throw(), and close() methods do on a generator object?
Functions Decorators & Functional Tools
What is the difference between *args and **kwargs, and how are they unpacked in a function call?
What are the limitations of lambda functions compared to named functions, and when should they be avoided in production code?
What is a list comprehension, and what are its advantages over using a for loop with append?
How do decorators work, and how can you ensure the original function's metadata is preserved?
How do decorators work under the hood? Explain the concept of a closure and how it allows a decorator to remember the state of the wrapped function.
Explain how a decorator works conceptually. How would you write a decorator that accepts its own arguments?
What are dictionary and set comprehensions, and when would you use them?
How does functools.lru_cache work, and how does it help with memoization?
What does functools.partial do, and when would you use it?
What is functools.reduce, and how does it differ from a simple loop?
What is the itertools module, and what kinds of problems does it help solve?
What is the walrus operator (:=), and in what situations is it useful?
What are positional-only and keyword-only parameters, and how do the / and * markers in a function signature work?
Language Idioms & Protocols
How does the sorted() function differ from the list.sort() method, and what is the role of the key parameter?
How do context managers work, and what is the difference between the __enter__/__exit__ and @contextmanager approaches?
What is Structural Pattern Matching (match/case) and how does it differ from a standard if/elif/else block?
What does it mean that Python's sort is stable, and why does that matter?
What is serialization with the pickle module, and what are its security concerns?
How do you implement an asynchronous context manager (async with), and how do __aenter__ and __aexit__ differ from their synchronous counterparts?
Concurrency Parallelism & The Gil
What is the Global Interpreter Lock (GIL), and given its existence, how do you write concurrent code that actually runs in parallel across multiple CPU cores?
Are Python threads 'real' native threads?
What is the GIL, and why was it originally implemented?
What is the difference between a thread and a coroutine in the context of the Python runtime?
Why is multiprocessing often preferred over threading for CPU-bound tasks in CPython?
What is the experimental 'free-threaded' build in Python 3.13 (PEP 703), and what are the trade-offs of removing the GIL for existing C extensions?
Compare and contrast threading, multiprocessing, and asyncio. When is each appropriate?
Explain what the GIL is and how it impacts multithreading in Python. If Python has a GIL, when would you still choose to use the threading module over multiprocessing?
What is the difference between a per-interpreter GIL introduced in 3.12 and the traditional GIL?
Asyncio & Asynchronous Programming
Explain the difference between preemptive multitasking (threading) and cooperative multitasking (asyncio). When is asyncio preferred over standard threading?
How does asyncio achieve concurrency without using multiple threads or processes?
When should you choose asyncio over threading for a high-concurrency task?
What is the difference between asyncio.gather() and asyncio.wait()?
How does the asyncio event loop work, and what happens to the loop when you execute a blocking I/O call inside an async function?
What makes an object awaitable in Python? Explain the relationship between coroutines, Tasks, and Futures.
How does the await keyword actually work under the hood?
Modules Imports & Data Essentials
What is the difference between f-strings, str.format(), and %-formatting?
What is the difference between a module and a package, and what role does __init__.py play?
What is the difference between a shallow copy and a deep copy, and how does the copy module handle nested objects in each case?
How does Python handle circular imports, and what are the common strategies to resolve them?
Why are strings immutable in Python, and what implications does that have for performance and memory?
How does the Python import system work, and what happens when you import a module for the second time?