Pythonlist_comprehension.py
List comprehension with condition
# Build a filtered, transformed list in one expression
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# [expression for item in iterable if condition]
evens_squared = [x**2 for x in numbers if x % 2 == 0]
print(evens_squared) # [4, 16, 36, 64, 100]
# Nested comprehension: flatten a 2D list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [n for row in matrix for n in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Dict comprehension: invert a dictionary
original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
print(inverted) # {1: 'a', 2: 'b', 3: 'c'}
Pythondataclass.py
Dataclass with defaults and post-init
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class User:
name: str
email: str
age: int = 0
tags: list[str] = field(default_factory=list) # mutable default — use field()
created_at: datetime = field(default_factory=datetime.now)
def __post_init__(self):
# Validate after __init__ runs
if self.age < 0:
raise ValueError(f"Age cannot be negative: {self.age}")
self.email = self.email.lower()
alice = User(name="Alice", email="ALICE@Example.com", age=30, tags=["admin"])
print(alice) # User(name='Alice', email='alice@example.com', ...)
print(alice.email) # alice@example.com — normalised in __post_init__
# Frozen dataclass: immutable (hashable, usable in sets/as dict key)
@dataclass(frozen=True)
class Point:
x: float
y: float
p = Point(1.0, 2.0)
# p.x = 3.0 # raises FrozenInstanceError
Pythoncontext_manager.py
Custom context manager with contextlib
from contextlib import contextmanager
import time
# contextmanager: turn a generator into a context manager
@contextmanager
def timer(label: str):
start = time.perf_counter()
try:
yield # code inside `with` block runs here
finally:
elapsed = time.perf_counter() - start
print(f"{label}: {elapsed:.4f}s")
with timer("sorting"):
data = sorted(range(100_000), reverse=True)
# Class-based context manager: __enter__ and __exit__
class TempDir:
def __init__(self, path): self.path = path
def __enter__(self): return self.path
def __exit__(self, exc_type, exc_val, exc_tb):
# exc_type is None if no exception occurred
print(f"Cleaning up {self.path}")
return False # don't suppress exceptions
Pythondecorator.py
Decorator with functools.wraps
import functools
import time
def retry(max_attempts: int = 3, delay: float = 1.0):
"""Decorator factory: retry a function on exception."""
def decorator(func):
@functools.wraps(func) # preserves __name__, __doc__, etc.
def wrapper(*args, **kwargs):
for attempt in range(1, max_attempts + 1):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts:
raise
print(f"Attempt {attempt} failed: {e}. Retrying...")
time.sleep(delay)
return wrapper
return decorator
@retry(max_attempts=3, delay=0.5)
def fetch_data(url: str) -> str:
# Simulates a flaky network call
import random
if random.random() < 0.7:
raise ConnectionError("Network timeout")
return f"Data from {url}"
Pythonasync_await.py
Async/await with concurrent tasks
import asyncio
async def fetch_user(user_id: int) -> dict:
await asyncio.sleep(0.1) # simulates I/O wait
return {"id": user_id, "name": f"User{user_id}"}
async def fetch_all_users(ids: list[int]) -> list[dict]:
# gather: run all coroutines concurrently (not sequentially)
tasks = [fetch_user(uid) for uid in ids]
return await asyncio.gather(*tasks)
async def main():
users = await fetch_all_users([1, 2, 3, 4, 5])
for u in users:
print(u)
# TaskGroup (Python 3.11+): structured concurrency with error propagation
async with asyncio.TaskGroup() as tg:
task1 = tg.create_task(fetch_user(10))
task2 = tg.create_task(fetch_user(20))
print(task1.result(), task2.result())
asyncio.run(main())
Pythongenerators.py
Generators and generator expressions
from typing import Generator
def fibonacci() -> Generator[int, None, None]:
"""Infinite Fibonacci sequence — lazy, O(1) memory."""
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# Take first 10 Fibonacci numbers
fib = fibonacci()
first_10 = [next(fib) for _ in range(10)]
print(first_10) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
# Generator expression: like list comprehension but lazy
# No [] around it — produces values one at a time
total = sum(x**2 for x in range(1_000_000)) # O(1) memory vs list
# Pipeline: chain generators
def read_lines(path):
with open(path) as f:
yield from f # yield each line lazily
def filter_empty(lines):
return (line.strip() for line in lines if line.strip())
# Memory-efficient pipeline — never loads whole file
# for line in filter_empty(read_lines("data.txt")):
# process(line)
Pythonunpacking.py
Unpacking and starred assignment
# Tuple unpacking
x, y, z = (1, 2, 3)
# Starred assignment: collect remaining items
first, *rest = [1, 2, 3, 4, 5]
print(first) # 1
print(rest) # [2, 3, 4, 5]
*init, last = [1, 2, 3, 4, 5]
print(init) # [1, 2, 3, 4]
print(last) # 5
head, *middle, tail = [1, 2, 3, 4, 5]
print(middle) # [2, 3, 4]
# Swap without temp variable
a, b = 1, 2
a, b = b, a
print(a, b) # 2 1
# Unpack in for loops
pairs = [(1, "one"), (2, "two"), (3, "three")]
for num, name in pairs:
print(f"{num}: {name}")
Pythoncollections_module.py
collections module: Counter, defaultdict, deque
from collections import Counter, defaultdict, deque
# Counter: count occurrences
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
counts = Counter(words)
print(counts) # Counter({'apple': 3, 'banana': 2, 'cherry': 1})
print(counts.most_common(2)) # [('apple', 3), ('banana', 2)]
# Counter arithmetic
a = Counter(["a", "a", "b"])
b = Counter(["a", "c"])
print(a + b) # Counter({'a': 3, 'b': 1, 'c': 1})
# defaultdict: no KeyError on missing keys
groups = defaultdict(list)
for word in words:
groups[word[0]].append(word) # group by first letter
print(dict(groups))
# deque: O(1) append/pop from both ends (list is O(n) for left ops)
dq = deque([1, 2, 3], maxlen=5)
dq.appendleft(0) # O(1)
dq.append(4) # O(1)
dq.popleft() # O(1)
print(list(dq))
Pythonpathlib_usage.py
pathlib for file system operations
from pathlib import Path
# Path operations — cross-platform, no os.path needed
base = Path("/tmp/myproject")
config = base / "config" / "settings.json" # / operator joins paths
print(config.parent) # /tmp/myproject/config
print(config.name) # settings.json
print(config.stem) # settings
print(config.suffix) # .json
# Create directories and write files
base.mkdir(parents=True, exist_ok=True)
config.parent.mkdir(exist_ok=True)
config.write_text('{"debug": true}')
# Read back
data = config.read_text()
# Glob: find files
py_files = list(Path(".").glob("**/*.py")) # recursive
for f in py_files:
print(f.relative_to(Path(".")))
# Check existence
if config.exists():
config.unlink() # delete
Pythonregex.py
Regular expressions with re module
import re
text = "Contact us at hello@example.com or support@thecodex.expert"
# Compile pattern for reuse (more efficient when used many times)
email_pattern = re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")
# findall: return all matches as a list
emails = email_pattern.findall(text)
print(emails) # ['hello@example.com', 'support@thecodex.expert']
# search: find first match anywhere in string
m = email_pattern.search(text)
if m:
print(m.group()) # hello@example.com
print(m.start()) # position in string
# Named groups: (?P<name>...)
date_pattern = re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})")
m = date_pattern.search("Date: 2026-06-10")
if m:
print(m.group("year")) # 2026
print(m.groupdict()) # {'year': '2026', 'month': '06', 'day': '10'}
# sub: replace with function
result = re.sub(r"\b\w{4}\b", lambda m: m.group().upper(), "this is a test")
print(result) # THIS is a TEST (4-letter words uppercased)
Pythontype_hints.py
Type hints: generics, Protocol, TypeVar
from typing import TypeVar, Generic, Protocol, runtime_checkable
T = TypeVar("T")
K = TypeVar("K")
V = TypeVar("V")
# Generic class
class Stack(Generic[T]):
def __init__(self) -> None:
self._items: list[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
def __len__(self) -> int:
return len(self._items)
s: Stack[int] = Stack()
s.push(1)
s.push(2)
# Protocol: structural subtyping (like Go interfaces)
@runtime_checkable
class Drawable(Protocol):
def draw(self) -> str: ...
class Circle:
def draw(self) -> str: return "○"
class Square:
def draw(self) -> str: return "□"
def render(shape: Drawable) -> None:
print(shape.draw())
render(Circle()) # works — Circle has draw() even without explicit subclassing
print(isinstance(Circle(), Drawable)) # True (runtime_checkable)
Pythonfunctools_tools.py
functools: lru_cache, partial, reduce
from functools import lru_cache, partial, reduce
import operator
# lru_cache: memoize expensive/recursive functions
@lru_cache(maxsize=None)
def fib(n: int) -> int:
if n < 2: return n
return fib(n - 1) + fib(n - 2)
print(fib(50)) # 12586269025 — computed instantly with caching
print(fib.cache_info()) # CacheInfo(hits=48, misses=51, ...)
# partial: pre-fill arguments
def power(base, exp): return base ** exp
square = partial(power, exp=2)
cube = partial(power, exp=3)
print(square(5)) # 25
print(cube(3)) # 27
# reduce: fold a sequence into a single value
product = reduce(operator.mul, [1, 2, 3, 4, 5])
print(product) # 120
# Equivalent to:
# result = 1
# for x in [1,2,3,4,5]: result *= x
Pythonexception_groups.py
Exception handling patterns
class DatabaseError(Exception):
"""Base class for database errors."""
class ConnectionError(DatabaseError):
def __init__(self, host: str, port: int):
self.host = host
self.port = port
super().__init__(f"Cannot connect to {host}:{port}")
def connect(host: str, port: int) -> None:
raise ConnectionError(host, port)
# Catch specific exceptions — most specific first
try:
connect("localhost", 5432)
except ConnectionError as e:
print(f"Connection failed: {e.host}:{e.port}")
except DatabaseError as e:
print(f"Database error: {e}")
except Exception as e:
print(f"Unexpected: {type(e).__name__}: {e}")
else:
print("Connected successfully") # runs only if no exception
finally:
print("Always runs — cleanup here") # always runs
# Re-raise with context
try:
int("not a number")
except ValueError as e:
raise RuntimeError("Failed to parse config") from e
# Original exception preserved in __cause__
Pythonclass_advanced.py
__slots__, properties, and classmethods
class Temperature:
__slots__ = ("_celsius",) # reduces memory; prevents arbitrary attribute creation
def __init__(self, celsius: float):
self._celsius = celsius
@property
def celsius(self) -> float:
return self._celsius
@celsius.setter
def celsius(self, value: float) -> None:
if value < -273.15:
raise ValueError(f"Temperature below absolute zero: {value}")
self._celsius = value
@property
def fahrenheit(self) -> float:
return self._celsius * 9/5 + 32
@classmethod
def from_fahrenheit(cls, f: float) -> "Temperature":
return cls((f - 32) * 5 / 9)
@staticmethod
def absolute_zero() -> float:
return -273.15
t = Temperature(100)
print(t.fahrenheit) # 212.0
t2 = Temperature.from_fahrenheit(32)
print(t2.celsius) # 0.0
print(Temperature.absolute_zero()) # -273.15
Python reference — Python overview · Python Course
Everything Python in one place — learning paths, reference, playground, and more.
Python Hub →