Cheat SheetsPython A–ZStdlib Power Tools

Stdlib Power Tools — Cheat Sheet

Python A–Z · 5 topics. Download the PDF or the Instagram carousel and share it.

Cheat Sheet · AiCanCode.org
Stdlib Power Tools
Python A–Z5 topicsQuick revision reference
1

collections — Counter, defaultdict & deque

Counter counts anything in one line, defaultdict removes key-existence boilerplate, deque gives O(1) queues — three imports that shorten half of all interview solutions.

  • Counter: most_common(k), zero for missing keys, arithmetic between counters
  • defaultdict(list) for grouping, defaultdict(int) for counting — no key checks
  • deque: O(1) append/pop on both ends — always use it for BFS queues
  • Counter(a) == Counter(b) is the cleanest anagram test
Counter solves whole problem categories
from collections import Counter

votes = ["asha", "ravi", "asha", "neha", "asha", "ravi"]
c = Counter(votes)
print(c)                        # Counter({'asha': 3, 'ravi': 2, 'neha': 1})
print(c.most_common(2))         # [('asha', 3), ('ravi', 2)]
print(c["missing"])             # 0 — no KeyError!

# Anagram check — one line
print(Counter("listen") == Counter("silent"))    # True

# Top-K frequent elements (LeetCode 347) — two lines
nums = [1, 1, 1, 2, 2, 3]
print([n for n, _ in Counter(nums).most_common(2)])   # [1, 2]

# Counter arithmetic — "can I build this word from these letters?"
letters = Counter("aabbcc")
word    = Counter("abc")
print(not (word - letters))     # True — nothing missing
2

itertools & functools — lru_cache, product, groupby & reduce

@lru_cache memoizes recursion in one decorator line; itertools generates combinations, permutations and products lazily — brute-force search and DP speedups for free.

  • @lru_cache memoizes by arguments (hashable only) — instant DP from recursion
  • combinations = unordered picks, permutations = ordered, product = nested loops
  • accumulate gives prefix sums; groupby groups CONSECUTIVE items (sort first!)
  • Everything in itertools is lazy — islice to take a finite window
lru_cache: recursion → DP with a decorator
from functools import lru_cache

@lru_cache(maxsize=None)          # or @cache in 3.9+
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(100))                    # instant — 354224848179261915075
print(fib.cache_info())            # hits=98 misses=101 ...

# Classic DP: climbing stairs / ways to reach n
@lru_cache(maxsize=None)
def ways(n):
    if n <= 1:
        return 1
    return ways(n - 1) + ways(n - 2)

# functools.partial — pre-fill arguments
from functools import partial
def power(base, exp): return base ** exp
square = partial(power, exp=2)
print(square(9))                   # 81

# functools.reduce — fold a sequence (use sparingly)
from functools import reduce
print(reduce(lambda a, b: a * b, [1, 2, 3, 4]))   # 24
3

datetime — Dates, Timezones & Durations

datetime + timedelta do date arithmetic; strftime/strptime convert to and from strings; and timezone-aware UTC datetimes are the only correct choice for backends.

  • datetime - datetime = timedelta; datetime + timedelta = datetime
  • strptime parses strings in, strftime formats out; ISO-8601 via isoformat()
  • Store/compute in aware UTC — datetime.now(timezone.utc); convert to IST only for display
  • Naive and aware datetimes cannot be compared — pick aware, everywhere
Dates subtract into durations
from datetime import datetime, timedelta, date

now = datetime.now()
placement_day = datetime(2026, 12, 1, 9, 0)

gap = placement_day - now                # timedelta
print(gap.days, "days left")

token_expiry = now + timedelta(hours=12)
print(now < token_expiry)                # True

# Date-only math
today = date.today()
last_monday = today - timedelta(days=today.weekday())
print("week started:", last_monday)

# timedelta knows seconds too
print(timedelta(days=1).total_seconds())  # 86400.0

# Compare timestamps naturally
t1 = datetime(2026, 7, 10, 14, 30)
t2 = datetime(2026, 7, 10, 18, 0)
print(max(t1, t2))                        # later one
4

Regular Expressions — the re Module

search finds, findall collects, sub replaces, groups extract — with raw strings, character classes and quantifiers making Python a text-processing power tool.

  • Always raw strings: r"\d+" — otherwise Python eats your backslashes
  • search anywhere vs match at start; findall returns group contents
  • .* is greedy (longest), .*? is lazy (shortest) — the #1 regex bug
  • Groups (...) extract; named groups (?P<name>...) document; \b bounds whole words
search / findall / sub / finditer / match
import re

log = "2026-07-10 ERROR user=asha code=500; 2026-07-10 INFO user=ravi code=200"

# search — first occurrence anywhere
m = re.search(r"code=(\d+)", log)
print(m.group(0), m.group(1))          # code=500  500

# findall — everything, capture groups only
print(re.findall(r"user=(\w+)", log))  # ['asha', 'ravi']

# sub — replace (mask phone numbers)
txt = "call 9876543210 or 9123456789"
print(re.sub(r"\d{10}", "XXXXXXXXXX", txt))

# Named groups — self-documenting extraction
pat = re.compile(r"(?P<date>\d{4}-\d{2}-\d{2}) (?P<level>\w+)")
for m in pat.finditer(log):
    print(m["date"], m["level"])        # 2026-07-10 ERROR / INFO

# match vs search: match anchors at position 0
print(re.match(r"\d+", "abc123"))      # None
print(re.search(r"\d+", "abc123"))     # <re.Match ... '123'>
5

Logging — Beyond print()

The logging module gives leveled, timestamped, routable logs — DEBUG/INFO/WARNING/ERROR/CRITICAL — configured once and used via module-level loggers; print() is for humans, logging is for systems.

  • getLogger(__name__) per module; configure levels/handlers once at the entry point
  • DEBUG for dev detail, INFO for lifecycle, WARNING for smells, ERROR/CRITICAL for failures
  • logger.exception() inside except logs the traceback automatically
  • Use %-style lazy args in log calls; f-strings evaluate even when filtered out
Configure once, log everywhere with levels
import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)-8s %(name)s: %(message)s",
    datefmt="%H:%M:%S",
)

logger = logging.getLogger(__name__)      # per-module logger

logger.debug("cache warm-up details")     # hidden (below INFO)
logger.info("server started on :8000")
logger.warning("disk 85% full")
logger.error("payment gateway timed out")

# 14:02:11 INFO     __main__: server started on :8000
# 14:02:11 WARNING  __main__: disk 85% full
# 14:02:11 ERROR    __main__: payment gateway timed out

# Lazy formatting — string built ONLY if the level passes
user_id, ms = "asha", 42
logger.info("user %s served in %d ms", user_id, ms)   # preferred
# vs logger.info(f"user {user_id}...")  — f-string always evaluates
Learn this free with Aria, your AI tutor → AiCanCode.org/learn/python