'==' checks value equality (calls __eq__), while 'is' checks object identity (verifies that id(a) == id(b)).
Mutable: list, dict, set, bytearray. Immutable: int, float, str, tuple, frozenset, bytes.
Python automatically caches short strings and identifier-like strings so the same object in memory can be reused.
A shallow copy creates a new object but keeps references to the original nested objects. A deep copy recursively copies all the content.
You need to create a higher-order wrapper function that takes arguments and returns the actual decorator.
It copies the original function's metadata (name, docstring) into the decorator's wrapper, so debugging and IDE assistance work correctly.
An iterator is an object with a __next__ method. A generator is a special case of an iterator, created by a function with yield or a generator expression.
MRO determines the method lookup order for multiple inheritance. Python uses the C3 algorithm, accessible via Class.mro().
classmethod takes a reference to the class (cls) as its first argument, while staticmethod receives no special arguments and behaves like a regular function inside the class namespace.
It strictly limits the set of instance attributes, preventing the creation of __dict__. This saves significant memory when creating millions of objects.
Metaclasses are 'classes for classes'. They define how class objects themselves are created (by default, this is type).
The primary mechanism is reference counting. Additionally, a generational GC (three generations) detects circular references.
The Global Interpreter Lock prevents multiple threads from executing bytecode at the same time, protecting memory management (reference counts).
Threads share memory but are limited by the GIL. Processes have their own memory, run in parallel on different cores, but require inter-process communication (IPC).
It's an infinite loop that tracks the state of tasks (Future/Task). When a task is waiting on I/O, the loop switches to another ready task.
gather is used to run tasks concurrently and await their results, while wait gives more flexible control (e.g., returning after the first one completes).