Python Cheatsheet
Standard Library
Use this Python reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
collections — Specialized Containers
from collections import ( Counter, defaultdict, OrderedDict, ChainMap, namedtuple, deque, UserDict, UserList, UserString ) # Counter c = Counter("abracadabra") # {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1} c.most_common(3) # top 3 c.update("aab") # add more counts Counter("abc") + Counter("aab") # combine # defaultdict from collections import defaultdict groups = defaultdict(list) for item in data: groups[item.key].append(item) # deque q = deque(maxlen=10) # fixed-size ring buffer q.append(1) # right q.appendleft(0) # left q.pop() # right q.popleft() # left O(1) unlike list q.rotate(2) # rotate right 2; negative = left # namedtuple Point = namedtuple("Point", ["x", "y"]) p = Point(1, 2); p.x; p._asdict(); p._replace(x=10) # ChainMap merged = ChainMap(user_config, defaults) # first wins on lookup
itertools — Iterator Building Blocks
from itertools import ( count, cycle, repeat, accumulate, chain, compress, dropwhile, filterfalse, islice, pairwise, starmap, takewhile, zip_longest, product, permutations, combinations, combinations_with_replacement, groupby ) # Infinite iterators count(10) # 10 11 12 13 ... count(1, 0.5) # 1.0 1.5 2.0 ... cycle([1, 2, 3]) # 1 2 3 1 2 3 ... repeat(42) # 42 42 42 ... repeat(42, 5) # 42 five times # Finite iterators list(accumulate([1, 2, 3, 4])) # [1, 3, 6, 10] (running sum) list(accumulate([1, 2, 3], lambda a, b: a * b)) # [1, 2, 6] list(chain([1, 2], [3, 4], [5])) # [1, 2, 3, 4, 5] list(chain.from_iterable([[1,2],[3,4]]))# [1, 2, 3, 4] list(compress("ABCDE", [1,0,1,0,1])) # ['A', 'C', 'E'] list(dropwhile(lambda x: x<5, [1,4,6,4,1])) # [6, 4, 1] list(takewhile(lambda x: x<5, [1,4,6,4,1])) # [1, 4] list(islice(count(10), 5)) # [10, 11, 12, 13, 14] list(filterfalse(lambda x: x%2, range(10))) # [0, 2, 4, 6, 8] list(pairwise([1, 2, 3, 4])) # [(1,2),(2,3),(3,4)] Python 3.10+ list(starmap(pow, [(2,3),(3,2)])) # [8, 9] list(zip_longest("ABC", "xy", fillvalue="-")) # [('A','x'),('B','y'),('C','-')] # Combinatoric iterators list(product("AB", repeat=2)) # [('A','A'),('A','B'),('B','A'),('B','B')] list(permutations("ABC", 2)) # all 2-length permutations list(combinations("ABC", 2)) # [('A','B'),('A','C'),('B','C')] list(combinations_with_replacement("AB", 2)) # [('A','A'),('A','B'),('B','B')] # groupby — consecutive equal keys (sort first!) data = sorted([{"t": "A", "v": 1}, {"t": "B", "v": 2}, {"t": "A", "v": 3}], key=lambda x: x["t"]) for key, group in groupby(data, key=lambda x: x["t"]): print(key, list(group))
functools — Functional Tools
from functools import ( reduce, partial, partialmethod, lru_cache, cache, cached_property, wraps, total_ordering, singledispatch, cmp_to_key ) reduce(lambda a, b: a + b, [1,2,3,4]) # 10 # Partial — fix some arguments def power(base, exp): return base ** exp square = partial(power, exp=2) square(5) # 25 # singledispatch — function overloading by type @singledispatch def process(arg): raise TypeError(f"Unsupported type: {type(arg)}") @process.register(int) def _(arg): return arg * 2 @process.register(str) def _(arg): return arg.upper() process(5) # 10 process("hi") # "HI" # cmp_to_key — use old-style comparison function with sort import functools functools.cmp_to_key(lambda a, b: a - b)
math — Math Functions
import math math.sqrt(16) # 4.0 math.isqrt(16) # 4 (integer sqrt, Python 3.8+) math.pow(2, 10) # 1024.0 (always float, unlike built-in pow) math.exp(1) # e math.log(100, 10) # 2.0 math.log2(8) # 3.0 math.log10(1000) # 3.0 math.log1p(x) # log(1+x) accurate for small x math.floor(3.7) # 3 math.ceil(3.2) # 4 math.trunc(3.9) # 3 math.fabs(-3.2) # 3.2 (float absolute value) math.factorial(10) # 3628800 math.gcd(12, 8) # 4 math.lcm(4, 6) # 12 (Python 3.9+) math.comb(10, 3) # 120 math.perm(10, 3) # 720 math.prod([1,2,3,4]) # 24 (Python 3.8+) math.fsum([0.1]*10) # 1.0 (exact floating-point sum) math.hypot(3, 4) # 5.0 math.atan2(y, x) # angle in radians math.degrees(math.pi) # 180.0 math.radians(180) # math.pi math.sin(math.pi/2) # 1.0 math.cos(0) # 1.0 math.tan(math.pi/4) # ~1.0 math.inf # float infinity math.nan # NaN math.e # 2.718... math.pi # 3.14159... math.tau # 6.28318... (2π) math.isinf(math.inf) # True math.isnan(math.nan) # True math.isfinite(1.0) # True math.isclose(0.1+0.2, 0.3, rel_tol=1e-9, abs_tol=1e-12) # True
random — Random Numbers
import random random.random() # float in [0.0, 1.0) random.uniform(1.0, 10.0) # float in [a, b] random.randint(1, 6) # int in [a, b] inclusive random.randrange(0, 100, 2) # like range() but random random.gauss(mu=0, sigma=1) # Gaussian distribution random.normalvariate(mu=0, sigma=1) random.choice([1, 2, 3]) # random element random.choices([1,2,3], weights=[1,2,3], k=5) # with replacement, weighted random.sample([1,2,3,4,5], 3) # without replacement random.shuffle(lst) # in-place shuffle random.seed(42) # reproducible results # Cryptographically secure import secrets secrets.randbelow(100) # [0, n) secrets.choice([1,2,3]) secrets.token_bytes(32) # random bytes secrets.token_hex(16) # hex string (32 chars) secrets.token_urlsafe(16) # URL-safe base64
datetime — Dates and Times
from datetime import date, time, datetime, timedelta, timezone # Create d = date(2024, 1, 15) t = time(14, 30, 0) dt = datetime(2024, 1, 15, 14, 30, 0) dt = datetime.now() # local time dt = datetime.utcnow() # UTC (deprecated in 3.12 — use below) dt = datetime.now(timezone.utc) # timezone-aware UTC # From string dt = datetime.fromisoformat("2024-01-15T14:30:00") dt = datetime.strptime("15/01/2024", "%d/%m/%Y") # To string dt.isoformat() # "2024-01-15T14:30:00" dt.strftime("%Y-%m-%d %H:%M:%S") # "2024-01-15 14:30:00" dt.strftime("%B %d, %Y") # "January 15, 2024" # Attributes dt.year, dt.month, dt.day dt.hour, dt.minute, dt.second, dt.microsecond dt.weekday() # 0=Monday, 6=Sunday dt.isoweekday() # 1=Monday, 7=Sunday dt.date() # date part dt.time() # time part # Arithmetic delta = timedelta(days=7, hours=2, minutes=30) dt + delta dt - delta dt2 - dt1 # → timedelta delta.days, delta.seconds, delta.total_seconds() # Timestamps dt.timestamp() # Unix timestamp (float) datetime.fromtimestamp(ts) # from Unix timestamp (local) datetime.fromtimestamp(ts, tz=timezone.utc) # UTC # Timezone from datetime import timezone, timedelta as td utc = timezone.utc est = timezone(td(hours=-5)) dt_utc = datetime.now(utc) dt_est = dt_utc.astimezone(est) # zoneinfo (Python 3.9+) — IANA tz database from zoneinfo import ZoneInfo tz = ZoneInfo("America/New_York") dt = datetime.now(tz)
os and sys
import os, sys # Process / environment os.getpid() # process ID os.getenv("HOME") # env variable (None if missing) os.environ["HOME"] # env variable (KeyError if missing) os.environ.get("VAR", "default") os.putenv("VAR", "value") # prefer os.environ["VAR"] = "value" # System info sys.platform # "linux", "darwin", "win32" sys.version # "3.12.0 ..." sys.version_info # sys.version_info(major=3, minor=12, ...) sys.argv # ["script.py", "arg1", "arg2"] sys.exit(0) # exit with code (0 = success) sys.stdin, sys.stdout, sys.stderr # Paths sys.path # module search path sys.prefix # Python installation directory # Recursion sys.getrecursionlimit() # default 1000 sys.setrecursionlimit(5000) # Sizes sys.getsizeof(obj) # object memory in bytes (shallow)
re — Regular Expressions
import re re.match(r"\d+", text) # match at start re.search(r"\d+", text) # first match anywhere re.findall(r"\d+", text) # list of all matches re.finditer(r"\d+", text) # iterator of match objects re.sub(r"\d+", "N", text) # replace all re.sub(r"\d+", "N", text, count=1) # replace first only re.subn(r"\d+", "N", text) # (new_str, count) re.split(r"\s+", text) # split re.fullmatch(r"\d{3}", "123") # entire string must match # Match object m = re.search(r"(\w+)\s(\w+)", text) m.group(0) # full match m.group(1) # first group m.groups() # all groups m.start(1) # start of group 1 m.span() # (start, end) of full match # Compile for reuse pattern = re.compile(r"\d+", re.IGNORECASE) pattern.search(text) # Common flags re.IGNORECASE # re.I re.MULTILINE # re.M — ^ and $ match line boundaries re.DOTALL # re.S — . matches \n too re.VERBOSE # re.X — allow whitespace and comments in pattern
json — JSON Serialization
import json # Serialize json.dumps(obj) # to string json.dumps(obj, indent=2) # pretty json.dumps(obj, sort_keys=True) json.dumps(obj, ensure_ascii=False) # allow non-ASCII json.dump(obj, file_obj) # to file # Deserialize obj = json.loads(s) # from string obj = json.load(file_obj) # from file # Custom types class DateEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.isoformat() return super().default(obj) json.dumps({"dt": datetime.now()}, cls=DateEncoder) # Custom decoder def date_hook(d): for k, v in d.items(): try: d[k] = datetime.fromisoformat(v) except (TypeError, ValueError): pass return d json.loads(s, object_hook=date_hook)
pathlib — Paths
from pathlib import Path p = Path.home() / ".config" / "app.json" p.exists(); p.is_file(); p.is_dir() p.read_text(); p.write_text("data") p.read_bytes(); p.write_bytes(b"data") p.mkdir(parents=True, exist_ok=True) p.unlink(missing_ok=True) list(p.parent.glob("*.json")) list(p.parent.rglob("*.py")) p.rename(new); p.replace(new) p.stem; p.suffix; p.name; p.parent str(p); p.as_posix()
subprocess — Run External Commands
import subprocess # Simple — capture output result = subprocess.run(["ls", "-la"], capture_output=True, text=True) result.returncode # 0 = success result.stdout # captured stdout result.stderr # captured stderr result.check_returncode() # raises CalledProcessError if non-zero # check=True raises CalledProcessError automatically result = subprocess.run(["git", "status"], check=True, capture_output=True, text=True) # Shell command (security risk with untrusted input) subprocess.run("ls -la | grep py", shell=True, check=True) # Stream output to console (no capture) subprocess.run(["python", "script.py"]) # With input result = subprocess.run(["cat"], input="hello\n", capture_output=True, text=True) result.stdout # "hello\n" # Get just the output output = subprocess.check_output(["git", "log", "--oneline"], text=True)
threading and multiprocessing
import threading def worker(n): print(f"thread {n}") t = threading.Thread(target=worker, args=(1,), daemon=True) t.start() t.join() # wait for thread to finish t.is_alive() # Lock lock = threading.Lock() with lock: shared_resource += 1 # Other sync primitives threading.RLock() # reentrant lock threading.Event() # event.set(), event.wait() threading.Semaphore(5) # limit concurrent access threading.Barrier(3) # wait until N threads reach barrier # Thread pool from concurrent.futures import ThreadPoolExecutor, as_completed with ThreadPoolExecutor(max_workers=4) as executor: futures = [executor.submit(worker, i) for i in range(10)] for future in as_completed(futures): result = future.result() # raises if worker raised # Process pool (for CPU-bound work, bypasses GIL) from concurrent.futures import ProcessPoolExecutor with ProcessPoolExecutor(max_workers=4) as executor: results = list(executor.map(cpu_task, data))
typing — Type Hints
from typing import ( Any, Union, Optional, Literal, List, Dict, Set, Tuple, FrozenSet, Sequence, Mapping, MutableMapping, Iterable, Iterator, Generator, Callable, TypeVar, Generic, Protocol, ClassVar, Final, TypedDict, NamedTuple, cast, overload, TYPE_CHECKING ) # Modern syntax (Python 3.9+) — use built-in generics instead of typing def f(x: list[int]) -> dict[str, int]: ... def g(x: tuple[int, str, float]): ... # Optional and Union def h(x: int | None) -> str | None: ... # Python 3.10+ def h(x: Optional[int]) -> Optional[str]: ... # older style # Callable def apply(fn: Callable[[int, str], bool]) -> None: ... # TypeVar T = TypeVar("T") def identity(x: T) -> T: return x # Protocol (structural subtyping) from typing import Protocol class Sized(Protocol): def __len__(self) -> int: ... # TypedDict class Movie(TypedDict): title: str year: int rating: float # TYPE_CHECKING — avoid circular imports at runtime if TYPE_CHECKING: from mymodule import HeavyType
dataclasses — Data Classes
from dataclasses import dataclass, field, asdict, astuple, replace @dataclass class Point: x: float y: float z: float = 0.0 _cache: dict = field(default_factory=dict, repr=False, init=False) p = Point(1.0, 2.0) asdict(p) # {'x': 1.0, 'y': 2.0, 'z': 0.0} astuple(p) # (1.0, 2.0, 0.0) replace(p, x=10) # new instance with x=10 @dataclass(frozen=True) # immutable + hashable @dataclass(order=True) # comparison operators @dataclass(slots=True) # __slots__ (Python 3.10+)
contextlib — Context Manager Utilities
from contextlib import ( contextmanager, asynccontextmanager, suppress, nullcontext, redirect_stdout, ExitStack, closing ) @contextmanager def managed(): setup() try: yield resource finally: teardown() with suppress(FileNotFoundError, PermissionError): os.remove("temp.txt") with redirect_stdout(open("out.txt", "w")): print("goes to file") # ExitStack — dynamically nest context managers with ExitStack() as stack: files = [stack.enter_context(open(f)) for f in filenames]
enum — Enumerations
from enum import Enum, IntEnum, Flag, auto class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 Color.RED # <Color.RED: 1> Color.RED.name # "RED" Color.RED.value # 1 Color(1) # Color.RED Color["RED"] # Color.RED list(Color) # [<Color.RED: 1>, ...] # auto() — automatic values class Direction(Enum): NORTH = auto() # 1 SOUTH = auto() # 2 # IntEnum — also an int class Status(IntEnum): OK = 200 NOT_FOUND = 404 Status.OK == 200 # True # Flag — bitwise combination class Permission(Flag): READ = auto() WRITE = auto() EXEC = auto() RWX = READ | WRITE | EXEC perm = Permission.READ | Permission.WRITE Permission.READ in perm # True
logging — Logging
import logging # Basic setup logging.basicConfig( level=logging.DEBUG, format="%(asctime)s %(levelname)s %(name)s: %(message)s", handlers=[ logging.StreamHandler(), logging.FileHandler("app.log"), ] ) # Log levels: DEBUG < INFO < WARNING < ERROR < CRITICAL logging.debug("detailed info") logging.info("general info") logging.warning("something unexpected") logging.error("an error occurred") logging.critical("serious error") logging.exception("error with traceback") # includes exc_info # Named loggers (preferred) logger = logging.getLogger(__name__) logger.info("message") logger.error("error: %s", error_msg) # lazy string formatting # Structured logging logger.info("user login", extra={"user_id": 42, "ip": "1.2.3.4"})
argparse — CLI Argument Parsing
import argparse parser = argparse.ArgumentParser(description="My tool") parser.add_argument("filename", help="input file") parser.add_argument("-v", "--verbose", action="store_true") parser.add_argument("-n", "--count", type=int, default=10) parser.add_argument("-o", "--output", metavar="FILE") parser.add_argument("--format", choices=["json", "csv", "text"]) parser.add_argument("--tags", nargs="+") # one or more values parser.add_argument("--flags", nargs="*") # zero or more args = parser.parse_args() args.filename args.verbose args.count
struct — Binary Data
import struct # Pack: format string → bytes data = struct.pack(">IH", 1234, 567) # big-endian uint32 + uint16 # Unpack: bytes → tuple values = struct.unpack(">IH", data) # (1234, 567) # Format characters # > big-endian, < little-endian, ! network (big), = native # b int8, B uint8, h int16, H uint16, i int32, I uint32 # l int32, L uint32, q int64, Q uint64, f float32, d float64 # c char (bytes of length 1), s bytes, x pad byte struct.calcsize(">IH") # 6 bytes # Struct class for repeated use s = struct.Struct(">IH") s.pack(1, 2) s.unpack(data)