Quick Reference · general-purpose programming language · v2
python cheat sheet v2 · single source of truth
Everything in Python is a name bound to an object. Master four mental models — name lookup (LEGB), object mutability, the iteration protocol, and the concurrency map — and the rest of the language is detail, not mystery.
core syntax & types
data structures
control & functions
oop · typing · concurrency
gotcha
★ most common
Distilled & cross-checked across: docs.python.org/3 · PEPs 572 · 634 · 695 · 703 · realpython.com · python.org "What's New" 3.10–3.14 · w3schools · geeksforgeeks. Verified 2026-08-27 against Python 3.14.7 / 3.13.15.
Scope: this is the general Python language reference (syntax, data model, stdlib idioms), valid for 3.12+. For 3.14 release-specific headliners — t-strings (PEP 750), deferred annotations (PEP 649/749), the officially-supported free-threaded build (PEP 779), multiple interpreters — see the dedicated Python 3.14 sheet. The two are maintained independently.
Part I · Foundations
01Run & Environmentstart here
python --versionCheck interpreter version.
python★Interactive REPL (colorized, multiline in 3.13+).
python script.py★Run a script file.
python -m moduleRun a module as a script (e.g. -m http.server).
python -c "print(1+1)"Run a one-liner.
python -i script.pyRun then drop into the REPL for inspection.
python -X dev script.pyDev mode — extra runtime warnings & checks.
if __name__ == "__main__":★Only run when executed directly, not on import.
02Variables & Assignmentnames → objects
x = 5★Bind a name to an object; no declaration, dynamic typing.
a, b = b, a★Tuple unpacking — the classic swap.
x += 1★Augmented assignment (-=, *=, /=, //=, **=, %=).
first, *rest = numsStarred unpacking; works in any position but once.
_, x, _ = row_ is the convention for "don't care".
if (n := len(data)) > 3:★Walrus := — assign inside an expression (3.8+).
x = y = []aliasChained assignment binds both names to the same object.
03Numbers & Operatorsarithmetic & logic
7 / 2 → 3.5 7 // 2 → 3★True division always floats; // floors (toward −∞).
7 % 2 → 1 divmod(7, 2)Modulo; divmod returns (quotient, remainder).
2 ** 10 pow(2, 10, m)Power; 3-arg pow = fast modular exponent.
x == y x is y★== value equality; is identity — use is only for None/singletons.
a and b a or b not aShort-circuit; returns an operand, not just a bool.
0 < x < 10Chained comparisons evaluate each operand once.
& | ^ ~ << >>Bitwise: and, or, xor, invert, shifts.
int("ff", 16) 0b101 0o17 0x1FBase conversion & literal prefixes; 1_000_000 separators OK.
04Numeric Precision & Mathfloat · decimal · math
0.1 + 0.2 == 0.3 → Falseieee-754Binary floats can't represent most decimals exactly.
math.isclose(a, b)★The correct float comparison.
Decimal("0.1") + Decimal("0.2")Exact decimal arithmetic (money) — construct from strings.
Fraction(1, 3)Exact rational arithmetic.
round(2.5) → 2 round(3.5) → 4Banker's rounding — half rounds to the nearest even.
math.floor · ceil · sqrt · log · pi · inf · nanCore math module; nan != nan — test with math.isnan.
statistics.mean · median · stdevDescriptive stats without NumPy.
10**100Python ints have arbitrary precision — no overflow.
05Strings & Methodsimmutable text
s.split(",") "-".join(xs)★Split / join — every method returns a new string.
s.strip() · lstrip() · rstrip()★Trim whitespace (or given chars).
s.replace(old, new)★Substring replacement.
s.startswith(p) · endswith(p)★Prefix/suffix test; also removeprefix/removesuffix (3.9+).
s.find(sub) → -1 s.index(sub) → raisesLocate a substring; in for a plain membership test.
s.upper · lower · title · casefoldCase transforms; casefold for i18n-safe comparison.
s.isdigit · isalpha · isidentifierContent predicates.
r"C:\path" b"bytes"Raw string (no escapes); bytes literal — str.encode() ↔ bytes.decode().
06f-strings & Format Spec{value:fill align width .prec type}
f"{name} is {age}"★Interpolation, evaluated at runtime.
f"{price:.2f}"★2 decimal places.
f"{n:,}" f"{p:.1%}"Thousands separator; percentage.
f"{x:>10}" f"{x:^10}" f"{x:08d}"Right / center align to width 10; zero-pad.
f"{n:b}" f"{n:x}" f"{n:e}"Binary, hex, scientific.
f"{age=}"Debug spec — prints age=2.
f"{obj!r}"Use repr() instead of str().
f"{f"{inner}"}"3.12+Quote reuse & nesting allowed since the PEP 701 rewrite.
07Truthiness & Nonewhat counts as False
False · None · 0 · 0.0 · "" · [] · {} · set()★The falsy values; everything else is truthy.
if items: if not items:★Idiomatic emptiness check — not len(x) > 0.
x is None x is not None★Always identity, never == None.
value = x or defaultFallback idiom — beware: rejects 0/""/[] too.
def __bool__(self): …Custom truthiness; falls back to __len__.
Part II · Data Structures
08Listsordered, mutable · O(1) append
nums.append(x) · extend(iter)★Add one item / all items from an iterable.
nums.insert(i, x)Insert at index — O(n); prefer deque for front inserts.
nums.pop(i) · remove(x)★Pop by index (default last) / remove first matching value.
nums.sort(key=fn, reverse=True)★In-place, stable Timsort; sorted() returns a new list.
nums.index(x) · count(x)First position / occurrences.
x in numsMembership is O(n) — use a set for hot paths.
nums.copy() nums[:]Shallow copy — nested mutables still shared.
09Tuples & Setsimmutable / unique · O(1) lookup
point = (3, 4) single = (1,)★Tuple — immutable; 1-item needs the trailing comma.
a = {1, 2, 3} set(iterable)★Set — unordered, unique, hashable elements only.
a | b a & b a - b a ^ b★Union · intersection · difference · symmetric diff.
a <= b a.isdisjoint(b)Subset test; no common elements.
a.add(x) · discard(x)discard never raises; remove does.
frozenset(a)Immutable set — usable as a dict key / set member.
{} → empty dict, not setgotchaEmpty set is set().
10Dictionarieskey → value · insertion-ordered
d.get(k, default)★Lookup without KeyError.
d.setdefault(k, [])Get, inserting a default if absent.
d.pop(k, default) · d.popitem()Remove by key / remove last-inserted pair.
d.items() · keys() · values()★Live views — reflect later changes.
d1 | d2 d1 |= d2★Merge (3.9+) — right side wins on conflicts.
dict(zip(keys, vals))Build from parallel sequences.
k in d★Membership checks keys, O(1).
for k in d: d.pop(k)runtime errorNever mutate a dict while iterating — iterate over list(d).
11Slice Notationseq[start:stop:step]
text[0] text[-1]★First; last (negative = from the end).
text[1:4]★Index 1, 2, 3 — stop is excluded.
text[:3] text[3:] text[:]From start; to end; shallow copy.
text[::2] text[::-1]★Every 2nd; reversed copy.
nums[2:5] = [a, b]Slice assignment can grow/shrink a list.
s = slice(1, 10, 2); seq[s]Slices are objects — reusable & nameable.
text[10:99999]Out-of-range slices never raise — they clamp.
12collectionsspecialized containers
Counter(words).most_common(3)★Frequency count + top-k in two calls.
defaultdict(list)★Auto-creates missing values — no key checks.
deque(xs, maxlen=n)★O(1) appendleft/popleft; bounded = rolling window.
namedtuple("Pt", "x y")Lightweight immutable record with named fields.
ChainMap(cli, env, defaults)Layered lookup across several dicts.
OrderedDict.move_to_end(k)Mostly legacy (dicts are ordered) — but this is LRU gold.
13heapq & bisectpriority & sorted access
heapq.heappush(h, x) · heappop(h)★Min-heap on a plain list — O(log n) each.
heapq.nsmallest(k, xs, key=fn)Top-k without a full sort (also nlargest).
heapq.heapify(xs)List → heap in place, O(n).
bisect.bisect_left(xs, x)Binary-search insertion point in a sorted list.
bisect.insort(xs, x)Insert keeping the list sorted.
Part III · Control Flow & Functions
14Control Flowbranching
if … elif … else:★Colon + indentation define blocks (4 spaces, PEP 8).
x if cond else y★Conditional expression (ternary).
pass ...No-op placeholder; Ellipsis often marks stubs.
assert cond, "msg"Debug-time invariant — stripped under python -O, never for validation.
15Pattern Matchingmatch / case · 3.10+
match cmd:
case "quit" | "exit":★Literal + or-pattern; first match wins, no fallthrough.
case [x, y, *rest]:Sequence pattern — destructures like unpacking.
case {"type": t, **extra}:Mapping pattern — extra keys are ignored unless captured.
case Point(x=0, y=y):Class pattern — matches type + attributes.
case [x, *_] if x > 0:Guard — extra condition after the pattern.
case _:★Wildcard — the "default"; binds nothing.
case CONSTANT:gotchaBare names capture, not compare — use case Colors.RED: (dotted).
16Loopsiteration
for x in iterable:★Works on anything implementing the iteration protocol.
for i, x in enumerate(xs, start=1):★Index + value; never range(len(xs)).
for a, b in zip(xs, ys, strict=True):★Lockstep; strict (3.10+) raises on length mismatch.
while (chunk := f.read(8192)):Walrus loop — read-and-test in one line.
break continue★Exit loop; skip to next iteration.
for … else: while … else:else runs only if no break — "search failed" idiom.
for x in xs: xs.remove(x)gotchaMutating while iterating skips items — iterate a copy.
17Iterators & Protocoliter / next / StopIteration
it = iter(xs); next(it, default)★Manual iteration; default avoids StopIteration.
class R:
def __iter__(self): return self
def __next__(self): …A custom iterator implements both methods.
iter(fn, sentinel)2-arg form: call fn until it returns the sentinel.
list(it); list(it) → []gotchaIterators are single-use — the second pass is empty.
reversed(seq) sorted(iterable)Reverse iterator; new sorted list from anything iterable.
18Built-in Functionsalways available
len · min · max · sum · abs · round★Aggregates; min/max accept key= and default=.
any(it) all(it)★Short-circuit boolean reduction over an iterable.
map(fn, xs) filter(pred, xs)Lazy transform/filter; comprehensions usually read better.
isinstance(x, (int, float))★Type check (accepts a tuple); prefer over type(x) ==.
getattr(obj, "name", default)Dynamic attribute access; also setattr, hasattr.
vars(obj) · dir(obj) · id · type · reprIntrospection: attribute dict, names, identity, class, repr.
input("? ") print(*xs, sep=", ", end="")Console I/O; print takes sep/end/file/flush.
19Functionssignatures
def f(x, y=1):★Defaults are evaluated once, at def time.
def f(*args, **kwargs):★Collect extra positional / keyword args.
f(*nums, **opts)Unpack into a call.
def f(a, /, b, *, c):Positional-only ← / · * → keyword-only.
return a, bMultiple returns = one tuple, unpacked at the call site.
def f():
"""Docstring."""First-statement string → f.__doc__, help(f).
functions are objectsPass, return, store them — the basis of decorators.
20Closures & Scopeglobal · nonlocal · late binding
def outer():
n = 0
def inner(): return nClosure — inner captures the variable, not its value.
nonlocal nRebind a name in the enclosing function.
global counterRebind a module-level name (use sparingly).
[lambda: i for i in range(3)]late bindingAll see the final i — fix: lambda i=i: i.
x += 1 (no declaration)gotchaAssignment makes x local → UnboundLocalError.
21Lambdas & Functionalfunctools · operator
lambda x: x * 2★Single-expression anonymous function.
sorted(xs, key=lambda p: p[1])★The #1 lambda use case: sort keys.
operator.itemgetter(1) · attrgetter("name")Faster, named alternatives to key-lambdas.
functools.partial(f, arg1)Pre-fill some arguments; returns a new callable.
functools.reduce(fn, xs, init)Fold an iterable to one value.
22Comprehensionsbuild collections concisely
[x*x for x in xs if x > 0]★List comp — filter then transform, eager.
{k: v for k, v in pairs} {x for x in xs}★Dict / set comprehensions.
[y for row in grid for y in row]Nested = flatten; clauses read left-to-right like loops.
[a if a else 0 for a in xs]Ternary before for maps; if after filters.
3+ levels of nestingreadabilitySwitch to explicit loops — comprehensions aren't a flex.
23Generatorslazy · one value at a time
def gen():
yield x★Pauses at each yield; state is kept between calls.
(x*x for x in xs)★Generator expression — no brackets needed as a sole arg: sum(x*x for x in xs).
yield from subgen()Delegate to another generator.
g.send(value) · g.close()Push a value into a paused generator; finalize it.
lines → parse → filter → sinkChain generators into memory-flat pipelines.
len(gen) · gen[0]typeerrorGenerators have no length or indexing — they only iterate.
24Decoratorswrap behavior
@my_decorator
def f(): …★Sugar for f = my_decorator(f).
def deco(fn):
@functools.wraps(fn)
def wrap(*a, **kw): return fn(*a, **kw)
return wrapCanonical shape; wraps keeps name/docstring.
@retry(times=3)Parameterized decorator = factory returning a decorator.
@cache @staticmethod @propertyStack them — applied bottom-up.
25Context Managerswith · guaranteed cleanup
with open("f.txt") as f:★Cleanup runs even on exception.
with open(a) as f, open(b) as g:Multiple managers; parenthesized groups OK (3.10+).
__enter__ / __exit__The protocol; __exit__ returning True suppresses the exception.
@contextmanager
def cm():
yield resourceGenerator → context manager; wrap the yield in try/finally.
contextlib.suppress(FileNotFoundError)Cleanly ignore a specific exception.
26itertoolsiterator algebra
chain(a, b) chain.from_iterable(xss)★Concatenate iterables lazily; flatten one level.
product(a, b) · permutations · combinationsCartesian product & combinatorics.
islice(gen, 10)★Slice an iterator — take the first n lazily.
groupby(xs, key=fn)Groups consecutive matches — sort by the key first.
accumulate(xs)Running totals (or any binary fn).
count(10) · cycle(xs) · repeat(x, n)Infinite/repeating iterators — pair with islice.
pairwise(xs) batched(xs, n)3.10 / 3.12+Adjacent pairs; fixed-size chunks.
27functoolsfunction tools
@functools.cache★Unbounded memoization (3.9+); @lru_cache(maxsize=128) to bound it.
@cached_propertyCompute once per instance, then behave as an attribute.
@singledispatchFunction overloading by the type of the first argument.
@total_orderingDefine __eq__ + one comparison; get the rest free.
partial · reduce · wrapsSee cards 21 & 24.
Part IV · Object-Oriented Python
28Classes & Instancesthe basics
class Dog:
species = "canine"
def __init__(self, name):
self.name = name★Class attribute (shared) vs. instance attribute.
@property
def area(self): …★Computed read-only attribute; add @area.setter for writes.
@classmethod
def from_json(cls, s): …Alternative constructors; receives the class.
@staticmethodNamespaced plain function; no implicit argument.
__slots__ = ("x", "y")Fixed attributes — less memory, no __dict__, faster access.
class C: items = []sharedMutable class attribute is shared by all instances.
29Magic (Dunder) Methodsoperator overloading
__repr__★Unambiguous, for developers; aim for eval-able output.
__str__Readable, for users; falls back to __repr__.
__eq__ + __hash__★Define together — objects equal ⇒ same hash; defining __eq__ alone makes the class unhashable.
__lt__ · __le__ · __gt__ · __ge__Ordering (or use @total_ordering).
__len__ · __getitem__ · __contains__Make it sized, indexable, and in-testable.
__iter__ · __next__The iteration protocol (card 17).
__call__Make instances callable like functions.
__add__ · __mul__ · __radd__ …Arithmetic operators; r-versions handle other + self.
__enter__ · __exit__Context-manager protocol (card 25).
30Inheritance & MROsuper · abc · mixins
class Puppy(Dog):
def __init__(self):
super().__init__()★super() follows the MRO, not just "the parent".
C.__mro__ C.mro()Method Resolution Order — C3 linearization, left-to-right.
class Base(ABC):
@abstractmethod
def run(self): …Abstract base class — can't instantiate until implemented.
class JSONMixin: …Mixins add one capability; list them before the base.
isinstance(x, Base) issubclass(C, Base)Runtime type relationships.
deep inheritance treesdesignPrefer composition — "has-a" beats "is-a" beyond ~2 levels.
31Dataclassesless boilerplate
@dataclass
class Point:
x: int
y: int = 0★Auto __init__, __repr__, __eq__; defaults after non-defaults.
@dataclass(frozen=True, slots=True)Immutable + memory-efficient (slots: 3.10+).
field(default_factory=list)★The only safe mutable default.
field(repr=False, compare=False)Exclude a field from repr/comparisons.
@dataclass(kw_only=True)3.10+Force keyword-only construction.
asdict(obj) astuple(obj)Recursive conversion for serialization.
32Enum · NamedTuple · TypedDictstructured alternatives
class Color(Enum):
RED = 1★Named constants; Color.RED.name / .value; also auto().
class Color(StrEnum): …3.11+Members are usable directly as strings.
class Pt(NamedTuple):
x: int
y: intTyped, immutable record — tuple behavior + names.
class User(TypedDict):
name: str
age: intType-checked dict shape — still a plain dict at runtime.
NotRequired[str]3.11+Optional TypedDict key.
Part V · Errors, I/O & Data
33Exceptionsfail gracefully
try: … except ValueError as e:★Catch the most specific type that applies.
except (TypeError, KeyError):Multiple types in one clause.
else: … finally: …else if no error; finally always.
raise ValueError("msg") from err★Chain causes — keeps the original traceback context.
raiseBare re-raise inside except preserves the traceback.
e.add_note("context")3.11+Attach extra info to an in-flight exception.
except* ValueError as eg:3.11+ExceptionGroup handling — one type from a batch.
except: passneverSwallows everything, incl. KeyboardInterrupt. At minimum: except Exception + log.
34File I/O & Pathlibread / write / paths
with open("f.txt", encoding="utf-8") as f:★Always state encoding — the platform default varies.
for line in f:★Line-by-line — memory-flat for huge files.
modes: r · w · a · x · rb · wbRead; overwrite; append; create-only (fails if exists); binary.
p = Path("data") / "file.txt"★/ operator joins paths, cross-platform.
p.read_text() p.write_text(s)★Whole-file one-liners with auto open/close.
p.glob("**/*.py") p.exists() p.stem · p.suffixRecursive matching; checks; name parts.
p.mkdir(parents=True, exist_ok=True)Safe directory creation.
35JSON & Serializationjson · csv · pickle
json.dumps(obj, indent=2)★Object → JSON string; dump writes to a file.
json.loads(s) json.load(f)★Parse from string / file.
json.dumps(o, default=str)Escape hatch for dates/Decimals; keys become strings.
csv.DictReader(f) csv.DictWriterRows as dicts; open the file with newline="".
pickle.load(untrusted)securityUnpickling can execute arbitrary code — trusted data only.
36Regex — re modulepattern matching on text
re.search(pat, s)★First match anywhere → Match or None.
re.match · re.fullmatchAnchored at start / must span the whole string.
re.findall(pat, s) · finditer★All matches as strings / as Match objects (lazy).
re.sub(pat, repl, s)★Replace; repl may be a function.
pat = re.compile(r"(?P<year>\d{4})")Precompile in loops; named groups → m.group("year").
m.group(1) · m.groups() · m.span()Capture access; match position.
.* (greedy)careGreedy by default; use .*? for lazy; always raw strings r"…".
37datetimedates · times · zones
datetime.now(tz=timezone.utc)★Aware "now" — prefer over naive utcnow() (deprecated).
date(2026, 7, 3) timedelta(days=7)Date literal; durations support + - * comparisons.
dt.strftime("%Y-%m-%d %H:%M")★Format → string.
datetime.strptime(s, "%d/%m/%Y")Parse ← string.
datetime.fromisoformat(s) · dt.isoformat()★ISO-8601 round-trip — the sane default format.
ZoneInfo("Asia/Kolkata")IANA timezones in the stdlib (3.9+) — no pytz needed.
naive vs awaregotchaComparing/mixing them raises — store UTC, convert at the edges.
Part VI · Typing, Async & Concurrency
38Type Hintsfor tooling, not runtime
def f(x: int) -> bool:★Checked by mypy/pyright — not enforced at runtime.
list[int] dict[str, int] tuple[int, ...]★Built-in generics (3.9+).
int | None★Union syntax (3.10+) — replaces Optional[int].
Callable[[int], str] Iterable[int]Function & protocol types from typing/collections.abc.
def first[T](xs: list[T]) -> T:3.12+PEP 695 inline generics — no TypeVar import.
type Vector = list[float]3.12+The type statement — a true, lazy type alias.
class Sized(Protocol):
def __len__(self) -> int: …Structural ("duck") typing — no inheritance required.
@override3.12+Checker verifies this actually overrides a parent method.
39Async / Awaitcooperative concurrency
async def fetch(): …
await fetch()★Coroutine — runs only when awaited or scheduled.
asyncio.run(main())★The single entry point — starts/stops the event loop.
await asyncio.gather(a(), b())★Run coroutines concurrently, collect results in order.
async with asyncio.TaskGroup() as tg:
tg.create_task(work())3.11+Structured concurrency — waits for all, cancels on failure.
async with asyncio.timeout(5):3.11+Deadline for a block of awaits.
async for x in stream: async with conn:Async iteration & context managers.
time.sleep(1) in async codeblocks loopBlocks everything — use await asyncio.sleep(1).
fetch() without awaitno-opCreates a coroutine object that never runs (RuntimeWarning).
40Threads, Processes & the GILparallelism
with ThreadPoolExecutor() as ex:
ex.map(fetch, urls)★Threads — right for I/O-bound work.
with ProcessPoolExecutor() as ex:★Processes — right for CPU-bound work; sidesteps the GIL.
fut = ex.submit(fn, x); fut.result()Single task → Future; as_completed() to stream results.
threading.Lock() → with lock:Guard shared mutable state.
GILOne thread executes Python bytecode at a time; I/O & C extensions release it.
free-threaded build3.14 supportedPEP 703 no-GIL CPython — experimental in 3.13, an officially supported build in 3.14 (PEP 779). True multi-core threads.
processes share nothingnoteArguments/results are pickled — big objects are expensive.
Part VII · Project, Tooling & Quality
41Modules, Packages & venvorganize & isolate
import module from pkg import x as y★Modules run once; later imports hit the cache.
pkg/__init__.pyMarks a package; runs on first import; controls from pkg import * via __all__.
python -m venv .venv★Isolated environment per project.
source .venv/bin/activate★Windows Git-Bash: source .venv/Scripts/activate.
pip install pkg pip freeze > requirements.txt★Install; snapshot exact versions.
pyproject.tomlModern single config for build, deps & tools (PEP 621).
from module import *avoidPollutes the namespace; hides where names come from.
42CLI, Env & OSscripts that take input
sys.argvRaw arguments; argv[0] is the script name.
p = argparse.ArgumentParser()
p.add_argument("--n", type=int)★Declarative CLI with auto --help.
os.environ.get("API_KEY")★Environment variables — never hardcode secrets.
subprocess.run([…], capture_output=True, check=True)Run external commands; list form avoids shell injection.
sys.exit(1)Non-zero = failure, for shells & CI.
43Loggingprint() for production
logging.basicConfig(level=logging.INFO)★One-line setup in the entry script only.
log = logging.getLogger(__name__)★Per-module logger — the standard pattern.
log.debug · info · warning · error · criticalSeverity ladder; default threshold is WARNING.
log.info("user %s", uid)Lazy %-formatting — skipped if the level is off.
log.exception("failed")Inside except: message + full traceback.
44Testingpytest-first
def test_add():
assert add(2, 2) == 4★pytest: plain functions + plain asserts.
with pytest.raises(ValueError):★Assert an exception is raised.
@pytest.mark.parametrize("a,b", [(1,2),(3,4)])One test, many cases.
@pytest.fixture
def db(): yield connReusable setup/teardown via injection.
unittest.mock.patch("mod.api_call")Replace collaborators; patch where it's used, not defined.
pytest -x -k "pattern" --lfStop at first fail; filter by name; rerun last failures.
45Debugging & Profilingfind it, then time it
breakpoint()★Drop into pdb right here (n=next, s=step, c=continue, p expr).
python -m pdb script.pyPost-mortem debugging from the start.
timeit.timeit(fn, number=10_000)Micro-benchmarks; or python -m timeit "expr".
python -m cProfile -s cumtime script.pyWhere the time actually goes.
sys.getsizeof(obj) tracemallocObject size; allocation tracking.
warnings.warn("deprecated", DeprecationWarning)Soft signals; -W error makes them fatal in CI.
46Common Pitfallshandle with care
def f(x=[]):gotchaMutable default shared across calls — use x=None sentinel.
rows = [[0]*3]*3gotchaThree references to one inner list — use a comprehension.
a is b (for values)gotchaSmall-int/string caching makes it "work" sometimes — use ==.
copy.copy(x) (nested)shallowInner mutables still shared — deepcopy when nesting.
json.py · random.py as filenamesshadowingYour file shadows the stdlib module — imports break mysteriously.
"a" + 1typeerrorNo implicit coercion — convert explicitly: "a" + str(1).
tuple1 += (x,) inside a listsubtleAugmented ops on immutables rebind — surprising inside containers.
Worth memorizing
is ≠ ==is checks identity; == checks value — is only for None
mutable defaultsevaluated once at def time — use None as a sentinel
copy ≠ deepcopycopy() is one level deep; nested mutables still shared
list * n[[0]*3]*3 repeats one inner list, not three
global vs nonlocalglobal → module scope; nonlocal → enclosing function
param orderpositional-only / normal *args keyword-only **kwargs
iterators die oncea consumed generator/iterator yields nothing on pass two
set/dict need hashablekeys & members must be immutable-ish (tuple ✓, list ✗)
EAFP over LBYLtry/except beats pre-checking in idiomatic Python
await ≠ callcalling a coroutine does nothing until awaited/scheduled
GIL rule of thumbI/O-bound → asyncio/threads · CPU-bound → processes
case NAME capturesbare names in match bind — dotted names compare
encoding="utf-8"always pass it to open(); platform defaults differ
except Exceptionnever bare except: — it eats KeyboardInterrupt too
sorted() is stableequal keys keep order — chain sorts from minor to major key
f"{x=}"the fastest debug print you'll ever type