Python is a high-level, interpreted programming language created by Guido van Rossum in 1991, emphasizing code readability through significant whitespace and a philosophy of "there should be one obvious way to do it." It's widely used across web development, data science, automation, machine learning, and systems programming, powered by a vast ecosystem of packages and an active global community. Python 3.14 (released October 2025) introduced deferred annotation evaluation, t-strings, and officially supported free-threading β marking one of the most significant runtime shifts in Python's history. The key to mastering Python isn't just knowing syntax β it's understanding when to use list comprehensions over loops, how duck typing works, and why context managers matter for resource safety.
26 tables, 362 concepts. Select a concept node to jump to its table row.
Table 1: Data Types
Python's built-in types are the foundation every program builds on. Knowing which are mutable, which are hashable, and how each behaves in memory keeps you out of the most common Python traps β like assuming bool is not an int, or that two distinct lists with equal contents are the same object.
| Type | Example | Description | |
|---|---|---|---|
x = 42 | Arbitrary-precision integers β no overflow limit unlike most languages. | ||
y = 3.14 | β’ Double-precision floating-point (64-bit IEEE 754) β’ beware rounding errors with exact comparisons. | ||
s = "hello" | β’ Immutable sequence of Unicode characters β’ supports f-strings, slicing, and a rich method surface. | ||
flag = True | β’ Subclass of int β True is 1 and False is 0β’ this surprises most newcomers | ||
arr = [1, 2, 3] | Mutable ordered sequence β the most versatile and commonly used collection type. | ||
d = {"key": "val"} | β’ Mutable mapping of unique keys to values β’ insertion-ordered since Python 3.7. | ||
t = (1, 2, 3) | β’ Immutable ordered sequence β’ hashable when elements are hashable β usable as dict keys. | ||
s = {1, 2, 3} | β’ Mutable unordered collection of unique hashable elements β’ O(1) membership test. | ||
fs = frozenset([1, 2]) | β’ Immutable version of setβ’ hashable β can be a dict key or set element. | ||
x = None | β’ Singleton representing absence of value β’ distinct from empty collections or zero | ||
b = b"data" | β’ Immutable sequence of byte values (0β255) β’ for binary data and network protocols | ||
ba = bytearray(b"x") | Mutable version of bytes β for in-place modification of binary data. | ||
r = range(10) | Immutable sequence representing an arithmetic progression β memory-efficient for iteration. | ||
z = 1 + 2j | β’ Numbers with real and imaginary parts β’ j suffix denotes the imaginary unit |
Table 2: Operators
Every Python operator looks familiar from other languages, but most carry one or two Python-specific subtleties β true vs floor division, modulo whose sign follows the divisor, right-associative **, short-circuit and/or that return operands instead of booleans. The newer additions (:= walrus, | for dicts) reflect Python's continuing language design.
| Operator | Example | Description | |
|---|---|---|---|
x + y, x - y, x * y | Addition, subtraction, multiplication β work on numbers and some sequences (like str, list). | ||
x / y | Always returns float even for integer operands β true division since Python 3. | ||
x // y | β’ Rounds down to nearest integer β’ result type follows operands ( int//int β int). | ||
x % y | Remainder β sign matches divisor, unlike C/Java where it matches the dividend. | ||
x ** y | β’ Raises x to power yβ’ right-associative and supports fractional/negative exponents | ||
x == y, x < y, x >= y | Equality and ordering β chainable like 1 < x < 10 (evaluates each pair once). | ||
x is y | Tests if objects are the same instance in memory β not value equality. | ||
x in y | β’ Checks if x exists in container yβ’ O(1) for sets and dicts | ||
x and y | Returns first falsy value or last value if all truthy β short-circuits. | ||
x or y | Returns first truthy value or last value if all falsy β short-circuits. | ||
not x | Boolean negation β returns True if x is falsy. | ||
x & y | β’ Bitwise AND of integers β’ also set intersection for sets | ||
x | y | β’ Bitwise OR of integers β’ also set union for sets | ||
x ^ y | β’ Bitwise exclusive OR β’ also symmetric difference for sets | ||
~x | β’ One's complement β inverts all bits β’ result is -(x+1). | ||
x << n | β’ Shifts bits left by nβ’ equivalent to multiplying by 2**n. | ||
x >> n | β’ Shifts bits right by nβ’ equivalent to floor-dividing by 2**n. | ||
(x := 5) | Assigns and returns value in a single expression β useful in while and comprehensions (3.8+). | ||
d1 | d2 | β’ Merges two dicts into a new dict β’ |β’ = updates in-place (Python 3.9+). |
Table 3: String Operations
Strings are immutable Unicode sequences with a rich method surface for searching, splitting, joining, and formatting. Modern code reaches for f-strings for interpolation, str.join for performant concatenation, and the removeprefix/removesuffix pair for safe edge trimming β and always passes encoding="utf-8" to open() to avoid locale-dependent surprises.
| Method | Example | Description | |
|---|---|---|---|
f"{x} + {y} = {x+y}" | β’ Fastest and most readable formatting β’ supports expressions, format specs, and nested quotes since 3.12. | ||
"{} {}".format(a, b) | String formatting with positional/keyword arguments β more verbose than f-strings. | ||
s.split(",") | β’ Splits into list by delimiter β’ default splits on any whitespace and removes empty strings | ||
",".join(items) | Concatenates an iterable into a single string β preferred over += in loops for performance. | ||
s.strip() | β’ Removes leading and trailing whitespace β’ lstrip()/rstrip() for one side only | ||
s.removeprefix("pre") | β’ Removes exact prefix or suffix if present β’ returns unchanged string otherwise (Python 3.9+). | ||
s.replace("old", "new") | β’ Returns copy with all occurrences replaced β’ optional count parameter to limit replacements | ||
s.upper() | β’ Case conversion β’ casefold() for aggressive case-insensitive comparisons across locales | ||
s.startswith("pre") | Checks prefix/suffix β accepts a tuple of multiple options. | ||
s.find("sub") | β’ Finds substring position β’ find() returns -1 if not found, index() raises ValueError. | ||
s.count("x") | Returns the number of non-overlapping occurrences of a substring. | ||
s.partition(":") | β’ Splits into 3-tuple (before, sep, after)β’ always returns 3 parts even if separator not found | ||
s.isdigit() | β’ Character-type checks β’ many variants: isalnum(), isspace(), islower(), isupper(). | ||
s.encode("utf-8") | β’ Converts str β bytes via encoding β’ bytes.decode("utf-8") reverses it | ||
s.center(20, "*") | β’ Pads string to a given width with fill character β’ useful for formatting output | ||
"42".zfill(5) | Pads with leading zeros to specified width β "00042". | ||
s.title() | β’ title() capitalizes each wordβ’ capitalize() only the first character of the whole string | ||
s.translate(str.maketrans("abc","ABC")) | Replaces characters per a mapping table β efficient for multi-character substitution. | ||
t"Hello {name}" | Template strings producing a Template object for custom processing and safe interpolation (Python 3.14+). | ||
"%s %d" % (s, n) | C-style formatting β replaced by f-strings but still seen in legacy code. |
Table 4: Slicing and Indexing
Slice syntax [start:stop:step] is the unified way to index Python sequences β zero-based, half-open, and quietly forgiving of out-of-range indices. The same three components handle reversal ([::-1]), shallow copies ([:]), every-other-element selection ([::2]), and reverse walks, making slicing one of the highest-leverage pieces of syntax to master.
| Pattern | Example | Description | |
|---|---|---|---|
s[0], s[2] | Zero-based indexing from start β first element is [0]. | ||
s[-1], s[-2] | Indexes from end β -1 is last element, -2 is second-to-last. | ||
s[1:4] | Elements from index 1 up to (but not including) 4 β half-open interval. | ||
s[:3] | From beginning to index 3 β equivalent to s[0:3]. | ||
s[2:] | From index 2 to end β includes the last element. | ||
s[:] | Creates a shallow copy of the entire sequence. | ||
s[::2] | Every 2nd element β third parameter is step size. | ||
s[::-1] | Reverses sequence β negative step iterates backward. | ||
s[4:1:-1] | From index 4 down to (but not including) 1. |
Table 5: Control Flow
Python's control-flow keywords stay deliberately small: if/elif/else driven by truthiness, two loop forms with the unusual else clause, and (since 3.10) structural match with rich pattern types. The match statement goes far beyond a switch β it destructures sequences, mappings, class instances, and supports OR patterns, guards, and wildcard captures in one readable block.
| Statement | Example | Description | |
|---|---|---|---|
if x > 0: print("pos") | Conditional execution β tests truthiness of expression. | ||
elif x == 0: print("zero") | Chain multiple conditions β only the first true branch executes. | ||
else: print("neg") | Executes when all preceding conditions are false. | ||
x if cond else y | Inline conditional β returns x if cond is true, else y. | ||
for i in range(5): print(i) | Iterates over any iterable object β most common loop type. | ||
while x > 0: x -= 1 | β’ Repeats while condition is truthy β’ check happens before each iteration | ||
break | Exits innermost enclosing loop immediately. | ||
continue | Skips to the next iteration of the innermost loop. | ||
for i in items: passelse: print("done") | Executes if loop completes without break β useful for search patterns. | ||
pass | Null operation β syntactic placeholder where a statement is required. | ||
match x: case 1: print("one") | Structural pattern matching β compares against literal values (Python 3.10+). | ||
case 1 | 2 | 3: | β’ Matches multiple values in one case arm using |β’ (Python 3.10+). | ||
case Point(x=x, y=y): | Destructures class instances by attribute names into local variables (Python 3.10+). | ||
case [first, *rest]: | Matches and unpacks sequences β *rest captures remaining items (Python 3.10+). | ||
case {"action": a}: | Matches dicts by key presence β **rest captures remaining keys (Python 3.10+). | ||
case x if x > 0: | Adds a condition to any pattern β branch only executes if guard is true (Python 3.10+). | ||
case _: | Catch-all pattern that matches anything β like default in other languages (Python 3.10+). |
Table 6: Functions
Functions are first-class values in Python β they can be passed, returned, default-parameterized, decorated, and unpacked from iterables. Two non-obvious facts dominate the rough edges: default arguments are evaluated once at definition time (the source of the mutable-default trap), and the / and * separators in signatures enforce positional-only and keyword-only calling conventions explicitly.
| Technique | Example | Description | |
|---|---|---|---|
def func(a, b): return a + b | β’ Creates a reusable code block β’ return without value returns None. | ||
def f(x, y=10): | β’ Parameters with default values β must come after required params β’ evaluated once at definition. | ||
f(x=1, y=2) | Named parameters β allows any order at call site and improves call-site clarity. | ||
def f(a, b, /, c): | Parameters before / cannot be passed by keyword β enforces positional calling (Python 3.8+). | ||
def f(a, *, b): | Parameters after bare * must be passed by keyword β prevents accidental positional misuse. | ||
def f(*args): | Variable positional arguments β collected as a tuple. | ||
def f(**kwargs): | Variable keyword arguments β collected as a dict. | ||
lambda x: x * 2 | Anonymous function β single expression only, no statements. | ||
"""Description.""" | First string in function body β accessible via __doc__ and used by help(). | ||
def f(x: int) -> int: | Optional annotations β not enforced at runtime but used by type checkers. | ||
f(*args, **kwargs) | Expands sequences and mappings into function arguments at call time. |
Table 7: Comprehensions and Generators
List, dict, and set comprehensions build a collection from an iterable in one expression β typically faster than the equivalent for/append loop and easier to read. Generator expressions and yield-based functions use almost the same syntax but produce lazy iterators, which is what lets Python stream gigabytes without loading them into memory.
| Technique | Example | Description | |
|---|---|---|---|
[x**2 for x in range(10)] | Creates a list from an iterable β faster and cleaner than for-loop append. | ||
[x for x in nums if x > 0] | Filters elements β condition acts as an inline filter on the iterable. | ||
[x+y for x in a for y in b] | Multiple for clauses β left-to-right nesting order (outer loop first). | ||
{k: v**2 for k, v in d.items()} | Creates a dict from an iterable β key-value pairs with unique keys (later values win). | ||
{x**2 for x in nums} | Creates a set β automatically deduplicates results. | ||
(x**2 for x in range(10)) | β’ Lazy evaluation β memory-efficient for large sequences β’ not stored in memory | ||
def gen(): yield x | Function with yield β pauses and resumes execution on each next() call. | ||
yield from iterable | Delegates to a subiterator β simplifies nested generators (Python 3.3+). |
Table 8: Classes and OOP
Python's class model favors flexibility over enforcement β no private attributes, no compile-time type checks, no formal interfaces. What you do get is a predictable MRO via C3 linearization, descriptor-driven property access, real multiple inheritance, and abc.ABC for defining enforced interfaces without metaclass boilerplate.
| Concept | Example | Description | |
|---|---|---|---|
class Dog: pass | Creates a new type β naming convention is PascalCase. | ||
def __init__(self, name): | Constructor β initializes instance when object is created. | ||
self.name = name | Per-object data β defined in __init__ or other methods via self. | ||
class Dog: species = "Canis" | Shared across all instances β defined at class level. | ||
def bark(self): | Functions bound to instance β first param is self by convention. | ||
class Puppy(Dog): | Derives from parent class β inherits attributes and methods. | ||
super().__init__(name) | Calls parent class method β handles multiple inheritance via MRO correctly. | ||
def age(self): | Getter method β accessed like an attribute but computed dynamically. | ||
def age(self, val): | Setter method β allows validation and side effects on attribute assignment. | ||
def factory(cls): | Method receives class, not instance β for alternative constructors. | ||
def util(): | Regular function in class namespace β no implicit first parameter. | ||
class C(A, B): | Inherits from multiple classes β uses C3 MRO to resolve method order. | ||
from abc import ABC, abstractmethodclass Shape(ABC): def area(self): ... | Enforces interface β subclasses cannot be instantiated until all abstract methods are implemented. | ||
def __repr__(self): | String representations β __repr__ for debugging, __str__ for users. | ||
__slots__ = ('x', 'y') | Declares fixed attributes β reduces memory and blocks __dict__ creation. | ||
def __new__(cls): | β’ Static method that creates the instance before __init__β’ needed for immutable subclasses | ||
def __init_subclass__(cls): | Hook called when a class is subclassed β lightweight alternative to metaclasses (Python 3.6+). |
Table 9: Magic Methods (Dunder Methods)
Dunder methods are how custom classes plug into Python's syntax β len(), obj[key], for x in obj, ==, +, with, even calling an instance like a function. Implementing the right small set turns a class from "useful" to "feels built-in," and the data model documents every hook the language consults.
| Method | Example | Description | |
|---|---|---|---|
def __init__(self): | Instance initialization β called when object is created. | ||
def __str__(self): | Informal string representation β used by str() and print(). | ||
def __repr__(self): | β’ Official string representation β should be valid Python when possible β’ fallback for __str__. | ||
def __len__(self): | β’ Returns length β called by len()β’ must return non-negative int. | ||
def __bool__(self): | β’ Truthiness check β called by bool() and in boolean contextsβ’ falls back to __len__. | ||
def __getitem__(self, key): | Indexing operator [] β enables subscript access. | ||
def __setitem__(self, k, v): | Item assignment [k] = v β makes object a mutable container. | ||
def __delitem__(self, key): | Deletion via del obj[key] β required for full mutable container protocol. | ||
def __iter__(self): | Returns an iterator β enables for-loop support and unpacking. | ||
def __next__(self): | Gets next value β raises StopIteration when exhausted. | ||
def __contains__(self, item): | Membership test in β should return boolean. | ||
def __enter__(self): | Context manager protocol β enables with statement. | ||
def __add__(self, other): | β’ Addition operator + β return new objectβ’ don't modify self. | ||
def __eq__(self, other): | β’ Equality operator == β default compares identityβ’ defining it disables __hash__ by default | ||
def __hash__(self): | β’ Makes instance hashable β required to use as dict key or set element β’ must be consistent with __eq__. | ||
def __lt__(self, other): | Comparison operators < and > β enables sorting. | ||
def __call__(self): | Makes instance callable like a function β enables obj() syntax. | ||
def __format__(self, spec): | Custom format spec support β called by format() and f-string {obj:spec} syntax. | ||
def __class_getitem__(cls, item): | Enables generic alias syntax MyClass[T] β supports runtime type parameterization. |
Table 10: Exception Handling
Exceptions are Python's primary error-signalling mechanism, with a four-clause structure (try/except/else/finally) and clean chaining via raise ... from .... Python 3.11's ExceptionGroup and except* give the language a way to express multiple concurrent failures β essential for asyncio.TaskGroup and structured-concurrency designs.
| Technique | Example | Description | |
|---|---|---|---|
try: risky()except ValueError: | Catches exceptions β specific types should precede general ones. | ||
except (ValueError, KeyError): | Catches multiple types in one clause β tuple of exception classes. | ||
except ValueError as e: | Captures the exception object β access message and attributes via e. | ||
else: print("success") | Runs if no exception raised in the try block β before finally. | ||
finally: cleanup() | β’ Always executes β even if exception raised or return encounteredβ’ for resource cleanup | ||
raise ValueError("msg") | Throws an exception β bare raise re-raises the current active exception. | ||
class MyError(Exception): | Define new exception types β inherit from Exception or a more specific subclass. | ||
raise NewError() from e | Links exceptions β preserves original cause for debugging tracebacks. | ||
raise ExceptionGroup("msg", [ValueError(), KeyError()]) | Groups multiple exceptions together β handled with except* (Python 3.11+). | ||
except* ValueError as eg: | Catches matching exceptions from an ExceptionGroup β multiple except* clauses can match (Python 3.11+). | ||
except: | β’ Catches all exceptions including KeyboardInterrupt β dangerous, hides bugsβ’ avoid |
Table 11: File Operations
File I/O uses a unified open() API parameterized by mode (r/w/a/b/+) and is best paired with with to guarantee cleanup on every exit path. Modern code increasingly leans on pathlib.Path for path manipulation and one-call read_text/write_text shortcuts β and remembers to pass encoding="utf-8" to dodge locale-dependent surprises across operating systems.
| Technique | Example | Description | |
|---|---|---|---|
with open("f.txt") as f: | Context manager β auto-closes file even if an exception occurs. | ||
for line in f: | Memory-efficient line iteration β preferred over readlines() for large files. | ||
content = f.read() | Reads entire file as string β memory-intensive for large files. | ||
line = f.readline() | Reads a single line β includes newline character. | ||
lines = f.readlines() | Returns list of all lines β newlines preserved in each element. | ||
f.write("text") | Writes string to file β doesn't add newline automatically. | ||
f.writelines(lines) | Writes a sequence of strings β no newlines added automatically. | ||
open("f.txt", "r") | Read mode β raises FileNotFoundError if file does not exist. | ||
open("f.txt", "w") | Write mode β truncates existing file or creates new. | ||
open("f.txt", "a") | β’ Append mode β adds to end of existing file β’ creates if absent | ||
open("f.bin", "rb") | β’ Binary mode β for non-text files β’ returns bytes objects | ||
open("f.txt", "x") | Exclusive creation β raises FileExistsError if file already exists. | ||
Path("f.txt").read_text(encoding="utf-8") | β’ Object-oriented path API β cleaner than os.pathβ’ copy()/move() added in 3.14. | ||
f = open("f.txt", encoding="utf-8") | Always specify encoding="utf-8" to avoid locale-dependent surprises on Windows. |
Table 12: Modules and Imports
Python's import system stitches code into namespaces using sys.path (search list), sys.modules (cache), and a finder/loader stack you can extend. Idiomatic code prefers explicit import over from X import *, uses relative imports inside packages, and guards script-only code behind if __name__ == "__main__": so the same file works as both a library and a script.
| Technique | Example | Description | |
|---|---|---|---|
import math | Imports entire module β access via math.func(). | ||
from math import sqrt | Imports specific names β directly accessible without module prefix. | ||
import numpy as np | Aliases module to a shorter name for convenience. | ||
if __name__ == "__main__": | Checks if script is run directly vs imported β guards executable code. | ||
from . import sibling | Within packages β dot notation for current/parent package. | ||
pkg/__init__.py | Makes directory a package β can initialize the package and control public API. | ||
sys.path.append(dir) | Module search paths β modify to add custom locations. | ||
importlib.import_module(name) | Dynamic imports β import by string name at runtime. | ||
from math import * | β’ Imports all public names β discouraged β’ pollutes namespace and hides origins |
Table 13: Common Built-in Functions
The built-ins show up in nearly every Python program β len, range, enumerate, zip, map, filter, sum, sorted, min/max, all/any, isinstance. Mastering their key= arguments, lazy-iterator returns, and edge cases (vacuous all([]), zip truncation, input always returning str) keeps day-to-day code short and correct.
| Function | Example | Description | |
|---|---|---|---|
len([1, 2, 3]) | Returns length of sequence or collection β calls __len__. | ||
range(start, stop, step) | Generates arithmetic sequence β stop is exclusive. | ||
enumerate(items, start=0) | Adds counter to iterable β returns (index, value) pairs. | ||
zip(list1, list2) | β’ Pairs elements from iterables β stops at shortest input β’ strict=True raises if lengths differ (3.10+). | ||
map(func, iterable) | Applies function to each element β returns lazy iterator. | ||
filter(predicate, items) | Filters elements where predicate is truthy β lazy iterator. | ||
sorted(items, key=func) | β’ Returns new sorted list β doesn't modify original β’ reverse=True for descending | ||
sum(numbers, start=0) | Sums a numeric iterable β optional starting value. | ||
min(items, key=func) | Returns smallest/largest element β optional key function. | ||
all([True, True, False]) | Returns True if all elements truthy or iterable is empty (vacuously true). | ||
any([False, False, True]) | Returns True if any element truthy. | ||
reversed(seq) | Returns a reverse iterator β doesn't modify original. | ||
isinstance(obj, type) | β’ Checks object type β accepts tuple of types β’ works with inheritance | ||
type(obj) | Returns object's exact type β for checking, prefer isinstance(). | ||
getattr(obj, "name", default) | Dynamic attribute access β getattr supports a default, avoids AttributeError. | ||
vars(obj) | β’ vars() returns __dict__β’ dir() lists all attributes and methods of an object | ||
abs(-5), divmod(17, 5) | β’ abs() returns magnitudeβ’ divmod(a, b) returns (quotient, remainder) as a tuple | ||
hex(255) β "0xff" | Converts integers to hexadecimal/octal/binary string representations. | ||
callable(func) | Returns True if object appears callable (has __call__). | ||
hash("hello") | β’ Returns integer hash of a hashable object β’ consistent within a process | ||
id(obj) | Returns object's memory address β guaranteed unique for its lifetime. | ||
input("Enter: ") | Reads a line from stdin β always returns string. | ||
print(*values, sep=" ", end="\n") | Writes to stdout β customizable separator and line ending. |
Table 14: Itertools Module
itertools is Python's grab-bag of iterator-combining building blocks β composable, lazy, and implemented in C for speed. The module covers infinite generators (count, cycle), combinatorics (combinations, permutations, product), grouping by adjacent runs (groupby), windowing (pairwise, batched), and reduction (accumulate).
| Function | Example | Description | |
|---|---|---|---|
chain(it1, it2) | Concatenates iterables β flattens multiple iterables into single iterator. | ||
chain.from_iterable(nested) | Flattens one level of nesting lazily β like chain(*nested) without unpacking. | ||
islice(it, start, stop) | Slices an iterator β doesn't support negative indices. | ||
compress('ABCDEF', [1,0,1,0,1,1]) | Filters data by a boolean selector iterable β yields A, C, E, F. | ||
filterfalse(lambda x: x<5, [1,4,6,3,8]) | Yields elements where predicate is false β opposite of filter(). | ||
starmap(pow, [(2,5), (3,2)]) | Applies function with arguments unpacked from each tuple in iterable. | ||
pairwise([1, 2, 3]) | Returns overlapping pairs of consecutive elements β (1,2), (2,3) (Python 3.10+). | ||
batched(range(10), 3) | Splits iterable into fixed-size tuples β last batch may be shorter (Python 3.12+). | ||
groupby(items, key=func) | Groups consecutive elements by key β input must be sorted by same key first. | ||
accumulate(nums, func) | β’ Running totals or reductions β default is addition β’ accepts any binary function | ||
takewhile(pred, it) | Yields elements while predicate is true β stops at first false. | ||
dropwhile(pred, it) | Skips elements while predicate is true β then yields all remaining. | ||
tee(iterable, n=2) | Splits one iterator into n independent iterators β use before an iterator is consumed. | ||
zip_longest(a, b, fillvalue=None) | Like zip() but continues to the longest input, filling shorter ones with fillvalue. | ||
combinations(items, r) | All r-length combinations β order doesn't matter, no repeated elements. | ||
combinations_with_replacement('AB', 2) | All r-length combinations allowing repeated elements β yields AA, AB, BB. | ||
permutations(items, r) | All r-length permutations β order matters, no repeated elements. | ||
product(a, b) | Cartesian product β equivalent to nested for-loops. | ||
count(start=0, step=1) | Infinite counter β useful with zip() or takewhile(). | ||
cycle([1, 2, 3]) | Repeats iterable infinitely β saves copy of all elements in memory. | ||
repeat(10, times=3) | Repeats object n times β infinite if times omitted. |
Table 15: Decorators
Decorators wrap a function or class to add behavior without changing the callsite. The syntax @decorator is sugar for func = decorator(func), extending naturally to parameterized decorators (three nesting levels) and to stacking multiple decorators (applied bottom-up). functools.wraps is mandatory in every wrapper to preserve the original's metadata.
| Technique | Example | Description | |
|---|---|---|---|
def func(): | Wraps function to modify behavior β sugar for func = decorator(func). | ||
def deco(f): def wrap(): return f() return wrap | Returns a wrapper function that replaces the original. | ||
def wrapper(): | Preserves function metadata ( __name__, __doc__, __wrapped__) β use inside every wrapper. | ||
def func(): | Returns a decorator β three-level nesting: deco(arg)(func). | ||
def f(): | Multiple decorators applied bottom-up: deco1(deco2(f)). | ||
class MyClass: | Modifies or replaces a class β callable receives and returns the class. | ||
| Memoizes function results with LRU eviction β cache_info() reports hits and misses. | ||
| Unbounded memoization β faster than lru_cache(None) as no eviction overhead (Python 3.9+). | ||
def value(self): | Computes property once per instance and caches as a normal attribute β delete attribute to reset (Python 3.8+). | ||
class C: | Generates all comparison methods from just __eq__ and one ordering method (__lt__, __le__, __gt__, or __ge__). | ||
def method(): | Built-in decorators: @classmethod, @staticmethod, @property. |
Table 16: Context Managers
Context managers β driven by __enter__/__exit__ (or __aenter__/__aexit__ for async) β guarantee deterministic resource cleanup even if the block raises. The contextlib module makes new managers trivial via the @contextmanager generator decorator and packages handy ones like suppress, closing, and the dynamic-composition ExitStack.
| Technique | Example | Description | |
|---|---|---|---|
with open("f") as f: | Ensures resource cleanup β calls __enter__ and __exit__. | ||
with open("a") as f1, open("b") as f2: | Manages multiple resources β left-to-right acquisition, right-to-left release. | ||
def ctx(): yield | Creates a context manager from a generator β yield separates setup from teardown. | ||
def __enter__(self): return self | Full protocol implementation β __exit__ receives (exc_type, exc_val, exc_tb). | ||
with suppress(FileNotFoundError): | Ignores specified exceptions β cleaner than try: ... except: pass. | ||
with closing(obj): | Calls close() on exit β for objects without a native context manager. | ||
with ExitStack() as stack: | Manages a variable number of context managers dynamically. |
Table 17: Async/Await (Asyncio)
asyncio delivers cooperative single-threaded concurrency: many waiting coroutines, one running at a time, no blocking. await is the only yield point β every awaited call must be non-blocking β and Python 3.11+ adds structured concurrency via TaskGroup plus deadline-based timeout(). The synchronization primitives (Lock, Event, Semaphore, Queue) mirror the threading module but are awaitable, not blocking.
| Technique | Example | Description | |
|---|---|---|---|
async def fetch(): | Defines a coroutine function β must be awaited or scheduled as a task. | ||
result = await coro() | Suspends coroutine β yields control to event loop until result is ready. | ||
asyncio.run(main()) | β’ Entry point β creates event loop and runs coroutine β’ closes loop on completion | ||
task = create_task(coro()) | Schedules coroutine to run concurrently with other tasks. | ||
async with TaskGroup() as tg: tg.create_task(coro()) | Structured concurrency β auto-cancels remaining tasks on failure (Python 3.11+). | ||
await gather(coro1(), coro2()) | Runs multiple coroutines concurrently β waits for all to complete. | ||
async with asyncio.timeout(5): | Context manager with deadline β raises TimeoutError if exceeded (Python 3.11+). | ||
await wait_for(coro(), timeout=5) | Adds timeout to a coroutine β raises TimeoutError if exceeded. | ||
async with asyncio.Lock(): | Mutex lock for async tasks β prevents concurrent access to shared state. | ||
event = asyncio.Event()await event.wait() | Notifies multiple tasks that something happened β set(), clear(), wait(). | ||
async with asyncio.Semaphore(10): | Limits number of concurrent coroutines accessing a resource. | ||
q = asyncio.Queue()await q.put(x)x = await q.get() | FIFO queue for producer-consumer patterns β task_done() + join() for completion tracking. | ||
await asyncio.sleep(1) | Non-blocking sleep β yields control to other coroutines. | ||
async for item in async_iter: | Iterates over an async iterable β calls __aiter__ and __anext__. | ||
async with resource: | Async context manager β awaits __aenter__ and __aexit__. |
Table 18: Type Hints
Type hints are runtime metadata that static checkers (mypy, pyright, pyre) consume to find bugs before they ship. PEP 585 (Python 3.9) made built-in generics work directly (list[int]), PEP 604 (3.10) introduced int | None unions, PEP 695 (3.12) added inline generic-parameter syntax, and PEP 649/749 (3.14) introduced deferred evaluation β annotations are no longer evaluated at import time, dramatically improving startup performance.
| Technique | Example | Description | |
|---|---|---|---|
x: int = 5 | Annotates variable type β not enforced at runtime. | ||
def f(x: int) -> str: | Parameter and return types β used by type checkers like mypy and pyright. | ||
items: list[int]d: dict[str, int] | Use built-in types directly as generics β no List/Dict imports needed (Python 3.9+). | ||
x: int | str | β’ Multiple allowed types β modern |β’ syntax replaces Union[int, str] (Python 3.10+). | ||
x: Optional[int] = None | β’ Shorthand for Union[T, None] β prefer T |β’ None in new code | ||
class Config(TypedDict): host: str port: int | Typed dict with specific key/value types β enables type checking on dict literals. | ||
f: Callable[[int], str] | Function type β list of param types then return type. | ||
class Sized(Protocol): def __len__(self): ... | Structural subtyping β duck typing with static type checking. | ||
x: Literal["a", "b"] | Restricts to specific values β useful for discriminated unions. | ||
T = TypeVar('T') | Generic type variable β for parametric polymorphism in functions and classes. | ||
def f[T](x: T) -> T: | Inline generic type variables on functions and classes β replaces TypeVar (Python 3.12+). | ||
type Vector = list[float] | Declares a type alias with lazy evaluation β replaces TypeAlias annotation (Python 3.12+). | ||
P = ParamSpec('P') | Captures the parameter types of a callable β essential for typing decorators that preserve signatures. | ||
def f(**kwargs: Unpack[Config]): | Types **kwargs using a TypedDict β enables per-key type checking (Python 3.12+). | ||
x: Any | β’ Disables type checking β avoid when possible β’ escape hatch | ||
def is_str(x) -> TypeIs[str]: | Narrows type in both if/else branches β safer than TypeGuard (Python 3.13+). | ||
def method(self): | Marks method as overriding parent β type checkers flag mismatches (Python 3.12+). | ||
def f(x: MyClass) -> None: | In Python 3.14+ annotations are not evaluated at import time β forward references work natively without quotes. |
Table 19: Regular Expressions
The re module exposes a single regex engine through both functional (re.search, re.findall, re.sub) and compiled (re.compile(...)) APIs. The biggest pitfalls are re.match vs re.search (anchored vs unanchored) and forgetting r"..." raw strings β without them, Python's own backslash processing eats half your pattern before the engine sees it.
| Function | Example | Description | |
|---|---|---|---|
re.search(r"\d+", s) | Searches anywhere in string β returns first match object or None. | ||
re.match(r"\d+", s) | Matches at start of string only β returns match object or None. | ||
re.fullmatch(r"\d+", s) | Matches entire string β both ^ and $ are implicit. | ||
re.findall(r"\d+", s) | Returns list of all matches β non-overlapping strings. | ||
re.finditer(r"\d+", s) | Returns iterator of match objects β memory-efficient for large inputs. | ||
re.sub(r"\d+", "X", s) | Replaces matches β accepts function as replacement for dynamic substitutions. | ||
re.split(r"\s+", s) | Splits by pattern β preserves groups in result if pattern has groups. | ||
p = re.compile(r"\d+") | Precompiles pattern β faster for reuse across many strings. | ||
m.group(1) | Captures subpatterns β group(0) is entire match, group(1) first capture. | ||
(?P<name>\d+) | Named capture β access via m.group('name') or m.groupdict(). | ||
r"\d+?" | ? after quantifier β matches as few characters as possible. | ||
r"\d+(?= px)" | Zero-width assertions β (?=...) lookahead, (?<=...) lookbehind β don't consume chars. | ||
re.search(r"a", s, re.I) | β’ Case-insensitive matching β combine flags with re.I |β’ re.M. | ||
re.search(r".+", s, re.S) | Makes . match newlines too β useful for multi-line text blocks. | ||
re.search(r"^word", s, re.M) | ^ and $ match start/end of each line, not just the string. | ||
r"\d+" | Prefix with r β avoids double-escaping backslashes in patterns. |
Table 20: Dataclasses and Modern Class Features
@dataclass (Python 3.7+) generates __init__, __repr__, and __eq__ from type-annotated attributes, with knobs for frozen, slots, and kw_only to fit specific use cases. For runtime validation and coercion at system boundaries, the ecosystem leans on pydantic; for richer feature sets without the validation cost, on attrs.
| Technique | Example | Description | |
|---|---|---|---|
class Point: x: float y: float | Auto-generates __init__, __repr__, __eq__ β less boilerplate (Python 3.7+). | ||
x: int = 0 | Default values β mutable defaults must use field(default_factory=...). | ||
items: list = field(default_factory=list) | Customizes field behavior β prevents shared mutable defaults across instances. | ||
| Makes instances immutable β enables hashing for use as dict keys. | ||
| Generates __slots__ for reduced memory β prevents dynamic attribute creation (Python 3.10+). | ||
| Forces keyword-only arguments in __init__ β prevents positional mistakes (Python 3.10+). | ||
def __post_init__(self): | Runs after __init__ β for computed fields or validation. | ||
temp: InitVar[int] | Init-only variable β not stored as field, available in __post_init__. | ||
asdict(obj) | Converts dataclass to dict/tuple β deep-copies nested dataclasses. | ||
class C: | Third-party alternative β more features than dataclasses (validators, converters, slots by default). | ||
class User(BaseModel): | Data validation library β runtime type checking, coercion, and JSON schema generation. |
Table 21: Enum Module
The enum module provides a way to define named constant sets with distinct identity, preventing typos and magic-string comparisons. Python 3.11 added StrEnum and IntEnum auto-values that produce the lowercased member name, and Python 3.12 improved the repr of enum members and simplified subclassing.
| Type | Example | Description | |
|---|---|---|---|
class Color(Enum): RED = 1 GREEN = 2 | Base class for enumerations β members have unique identity and are accessed as Color.RED. | ||
RED = auto() | Automatically assigns values β default is sequential integers starting at 1. | ||
class Status(IntEnum): OK = 200 | Enum whose members are also int β compatible with integer APIs. | ||
class Direction(StrEnum): NORTH = auto() | Members are also str β auto() generates the lowercased member name (Python 3.11+). | ||
class Perm(Flag): READ = auto() WRITE = auto() | β’ Members support bitwise operations β combine with |β’ , test with in. | ||
class Mode(IntFlag): R = 4 W = 2 | Flag + int compatibility β members behave as integers for system calls and bitmasks. | ||
list(Color) | Enumerates all members in definition order. | ||
Color(1), Color["RED"] | Access by value ( Color(1)) or by name (Color["RED"]). | ||
Color.RED.value, Color.RED.name | Access the raw value or the member name string. |
Table 22: Collections Module
The collections module provides specialized container datatypes that extend Python's built-in dict, list, set, and tuple. deque is the go-to for O(1) queue operations, OrderedDict retains its usefulness for LRU implementations despite regular dicts being ordered since 3.7, and Counter eliminates a common tally-building loop pattern entirely.
| Type | Example | Description | |
|---|---|---|---|
from collections import dequedq = deque([1,2,3], maxlen=5) | β’ Double-ended queue β O(1) append and pop on both ends β’ list.pop(0) is O(n). | ||
dq.appendleft(0)dq.popleft() | Efficient left-side operations β core advantage over list for queue usage. | ||
deque(maxlen=10) | β’ Bounded deque β oldest items auto-discarded when full β’ perfect for sliding windows | ||
defaultdict(list) | Dict that auto-creates missing keys using a factory function. | ||
Counter("abracadabra") | Dict subclass for counting hashable objects β most_common(n) returns top-n items. | ||
c1 + c2, c1 - c2, c1 & c2 | β’ Supports +, -, & (intersection), |β’ (union) β results keep only positive counts. | ||
c.total() | Returns sum of all counts (Python 3.10+). | ||
Point = namedtuple('Point', 'x y') | Tuple with named fields β immutable, memory-efficient alternative to a class. | ||
OrderedDict() | β’ Dict that remembers insertion order and supports move_to_end()β’ still useful for LRU caches | ||
od.move_to_end("key") | Moves key to end (or beginning with last=False) β key primitive for LRU cache implementation. | ||
ChainMap(local, global_, builtins) | β’ Groups multiple dicts β searches sequentially without copying β’ write goes to first map | ||
class MyDict(UserDict): | Subclass-friendly wrappers around dict/list β safer to subclass than the built-ins directly. |
Table 23: Concurrency
Python offers three concurrency models: threading (shared memory, GIL-limited for CPU work, good for I/O), multiprocessing (separate processes, true parallelism, higher overhead), and asyncio (cooperative single-thread, ultra-low overhead, requires async-aware code). concurrent.futures wraps both threading and multiprocessing behind one uniform executor interface; Python 3.14 adds InterpreterPoolExecutor for sub-interpreter concurrency without the IPC overhead of full processes.
| Technique | Example | Description | |
|---|---|---|---|
with ThreadPoolExecutor(max_workers=4) as ex: fut = ex.submit(func, arg) | β’ Thread pool β best for I/O-bound tasks β’ GIL limits CPU parallelism | ||
with ProcessPoolExecutor() as ex: fut = ex.submit(func, arg) | β’ Process pool β true CPU parallelism β’ data is pickled between processes | ||
list(ex.map(func, items)) | Parallel map β returns results in submission order, raises first exception encountered. | ||
fut.result(timeout=5) | Blocks until result available β re-raises any exception thrown by the worker. | ||
for f in as_completed(futures): | Yields futures as they complete β better throughput than waiting in submission order. | ||
with InterpreterPoolExecutor() as ex: | Runs tasks in sub-interpreters β true parallelism without pickle overhead (Python 3.14+). | ||
t = Thread(target=f, args=(1,))t.start(); t.join() | Spawns a native OS thread β use daemon=True to die with main thread. | ||
lock = Lock()with lock: | Mutex for shared state β with lock: is preferred (auto-releases on exceptions). | ||
e = Event()e.set(); e.wait() | Allows threads to signal each other β wait() blocks until set(). | ||
sem = Semaphore(3) | Limits concurrent access to n threads β acquire() decrements, release() increments. | ||
with Pool() as pool: pool.map(func, items) | Higher-level multiprocessing API β automatically manages worker process lifecycle. | ||
q = mp.Queue()q.put(x); q.get() | Process-safe queue β IPC via pickle across process boundaries. | ||
python3.14 -X gil=0 | Python 3.14 makes free-threading production-ready (PEP 779) β true thread parallelism possible. |
Table 24: Logging Module
Python's logging is a hierarchical system: every logger is a node in a tree rooted at the root logger, and events propagate upward unless propagate=False. Application code should always call logging.getLogger(__name__), let libraries configure nothing themselves, and leave root-level configuration to the application entry point.
| Technique | Example | Description | |
|---|---|---|---|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") | β’ Configures root logger β one-time call for simple scripts β’ must be before first log call | ||
logger = logging.getLogger(__name__) | β’ Gets or creates a named logger β hierarchy via dot notation β’ always use __name__. | ||
logger.debug("...")logger.info("...")logger.warning("...")logger.error("...")logger.critical("...") | Five levels: DEBUG < INFO < WARNING < ERROR < CRITICAL β only events at or above set level are emitted. | ||
h = logging.StreamHandler()logger.addHandler(h) | Outputs to stderr (default) or any stream β standard handler for console output. | ||
h = logging.FileHandler("app.log") | Writes to a file β use RotatingFileHandler for size-limited rotation. | ||
RotatingFileHandler("app.log", maxBytes=1e6, backupCount=3) | Rotates log file when it reaches maxBytes β keeps backupCount backups. | ||
fmt = Formatter("%(asctime)s - %(name)s - %(message)s")h.setFormatter(fmt) | Controls log record format β standard attributes include asctime, name, levelname, message. | ||
except Exception: logger.exception("Error") | Logs at ERROR level plus the full stack trace β use inside except blocks. | ||
logger.propagate = False | Stops log records bubbling up to parent loggers β avoids duplicate output. | ||
logging.config.dictConfig(cfg) | Configures logging from a dict or file β preferred for production over basicConfig. | ||
adapter = LoggerAdapter(logger, {"req_id": id}) | Adds contextual data to every log call without modifying the message format. |
Table 25: Virtual Environments and Packaging
Isolation is the first principle: one project, one environment, so dependency versions never interfere. venv is the built-in option (zero install, always available), while uv (Astral) is a fast Rust-based alternative that manages both environments and Python installations with near-instant dependency resolution.
| Tool | Example | Description | |
|---|---|---|---|
python -m venv .venv | Creates a virtual environment β installs pip + copies/symlinks interpreter. | ||
source .venv/bin/activate.venv\Scripts\activate | Activates environment β modifies PATH so python/pip point to venv. | ||
pip install requestspip install -r requirements.txt | Installs packages β -r installs from requirements file. | ||
pip freeze > requirements.txt | Snapshots current installed packages with pinned versions. | ||
uv init example | Creates a new project with pyproject.toml β fast Rust-based tool (Astral). | ||
uv run script.py | Runs script in an isolated, auto-created environment β no manual activation needed. | ||
uv add requests | Adds dependency to pyproject.toml and updates lockfile atomically. | ||
uv sync | Installs dependencies from lockfile β reproduces exact environment. | ||
uv python install 3.12 | Downloads and installs a specific Python version β managed alongside venv. | ||
[project]name = "myapp"requires-python = ">=3.11" | β’ Modern packaging standard β replaces setup.pyβ’ supported by pip, uv, poetry, flit | ||
pyenv install 3.11.5pyenv local 3.11.5 | Manages multiple Python versions side-by-side β sets .python-version file per directory. | ||
poetry new projectpoetry add requests | Package manager with lockfile and publishing support β poetry install reproduces env. |
Table 26: Advanced Patterns and Best Practices
These patterns represent idiomatic Python thinking: prefer iteration over indexing, exploit descriptors and __slots__ for performance-critical classes, compose with functools.partial (and Python 3.14's Placeholder for gap filling), and exploit generators for lazy pipelines that process data without materializing everything in memory.
| Technique | Example | Description | |
|---|---|---|---|
evens = (x for x in data if x%2==0)result = sum(evens) | β’ Chains generators lazily β never materializes intermediate lists β’ memory-efficient for large datasets | ||
double = partial(mul, 2) | Pre-fills arguments β creates specialized callable from a general function. | ||
f = partial(pow, ..., 2) | Marks positional gaps in partial() that callers must fill β ... is the Placeholder (Python 3.14+). | ||
reduce(lambda a,b: a+b, nums) | Folds a sequence left-to-right into a single value. | ||
def __get__(self, obj, type): | Implements per-attribute access β foundation for property, classmethod, staticmethod. | ||
__slots__ = ("x", "y") | Replaces per-instance __dict__ with fixed memory layout β reduces RAM and speeds attribute access. | ||
while chunk := f.read(8192): | β’ Assignment expression β assigns and evaluates in one step β’ avoids repeated calls | ||
def f(a, b, /, c): | β’ / separator β a, b can only be passed by positionβ’ prevents API-breaking renames | ||
def f(*, a, b): | * separator β a, b must be passed by keyword. | ||
class Meta(type): def __new__(mcs, ...): | Controls class creation β used by ORMs, ABCs, and plugin registries. | ||
def __init_subclass__(cls, **kw): | Hook called when a class is subclassed β simpler plugin registration than metaclasses. | ||
def __new__(cls): if not cls._instance: cls._instance = super().__new__(cls) return cls._instance | Ensures one instance via __new__ β thread-safe version requires a lock. | ||
tmpl = t"Hello {name}" | β’ Like f-strings but deferred β returns a Template object instead of a stringβ’ enables safe HTML/SQL generation (Python 3.14+). | ||
def f() -> MyClass: | β’ Annotations are not evaluated at import time in Python 3.14+ β forward references require no quotes β’ use annotationlib to evaluate explicitly | ||
import concurrent.interpreters | New in Python 3.14 (PEP 734) β runs code in isolated sub-interpreters with true parallelism via InterpreterPoolExecutor. |