Python
Data Types#
| category | types |
|---|
| text | str |
| numeric | int, float, complex |
| sequence | list, tuple, range |
| mapping | dict |
| set | set, frozenset |
| boolean | bool |
| binary | bytes, bytearray, memoryview |
| none | NoneType |
Keywords#
Python reserves 35 hard keywords (plus the soft keywords match and case for structural pattern matching since 3.10). Reserved keywords cannot be used as identifiers; soft keywords are only special in the relevant context.
| category | keywords |
|---|
| values | True, False, None |
| logical | and, or, not |
| identity | is |
| membership | in |
| branching | if, elif, else |
| looping | for, while, break, continue, pass |
| pattern | match, case 𐃏 |
| functions | def, return, lambda, yield |
| classes | class |
| exceptions | try, except, finally, raise, assert |
| imports | import, from, as |
| scoping | global, nonlocal |
| async | async, await |
| context | with |
| deletion | del |
A live list is available via import keyword; keyword.kwlist (and keyword.softkwlist for soft keywords).
Time Complexities #
lists#
| operation | time complexity |
|---|
sequence.append(item) | \(\mathcal{O}(1)\) |
sequence.pop(item) | \(\mathcal{O}(1)\) |
sequence.insert(0,item) | \(\mathcal{O}(n)\) |
sequence.pop(item,0) 𐃏 | \(\mathcal{O}(n)\) |
sequence[index] | \(\mathcal{O}(1)\) |
sequence[index]=value | \(\mathcal{O}(1)\) |
item in sequence | \(\mathcal{O}(n)\) |
len(sequence) | \(\mathcal{O}(1)\) |
sequence.extend(iterable) | \(\mathcal{O}(k)\) |
sequence + other_sequence | \(\mathcal{O}(n+k)\) |
sequence[index:index+k] | \(\mathcal{O}(k)\) |
sequence.index(item) | \(\mathcal{O}(n)\) |
sequence.count(item) | \(\mathcal{O}(n)\) |
for item in sequence: | \(\mathcal{O}(n)\) |
double-ended queue (deque)#
| operation | description | time complexity |
|---|
queue.append(item) | Add item to right end | \(\mathcal{O}(1)\) |
queue.appendleft(item) | Add item to left end | \(\mathcal{O}(1)\) |
queue.pop() | Remove and return item from right end | \(\mathcal{O}(1)\) |
queue.popleft() | Remove and return item from left end | \(\mathcal{O}(1)\) |
queue.extend(iterable) | Add all elements from iterable to right end | \(\mathcal{O}(k)\) |
queue.extendleft(iterable) | Add all elements from iterable to left (reversed) | \(\mathcal{O}(k)\) |
queue.remove(value) | Remove first occurrence of value | \(\mathcal{O}(n)\) |
queue.rotate(n) | Rotate n steps right (negative for left) | \(\mathcal{O}(k)\) |
queue.clear() | Remove all elements | \(\mathcal{O}(n)\) |
queue.count(value) | Count occurrences of value | \(\mathcal{O}(n)\) |
queue.index(value) | Find index of first occurrence of value | \(\mathcal{O}(n)\) |
queue.reverse() | Reverse elements in place | \(\mathcal{O}(n)\) |
item in queue | Check if item exists in queue | \(\mathcal{O}(n)\) |
queue[0] or queue[-1] | Access first or last element | \(\mathcal{O}(1)\) |
queue[i] | Access element at index i | \(\mathcal{O}(n)\) |
for item in queue | Iterate through all elements | \(\mathcal{O}(n)\) |
dictionary#
| operation | time complexity |
|---|
mapping[key]=value | \(\mathcal{O}(1)\) |
mapping[key] | \(\mathcal{O}(1)\) |
mapping.get(key) | \(\mathcal{O}(1)\) |
mapping.pop(key) | \(\mathcal{O}(1)\) |
key in mapping | \(\mathcal{O}(1)\) |
for k, v in mapping.items() | \(\mathcal{O}(n)\) |
next(iter(mapping)) | \(\mathcal{O}(1)\) |
next(reversed(mapping)) | \(\mathcal{O}(1)\) |
value in mapping.values() | \(\mathcal{O}(n)\) |
mapping.update(iterable) | \(\mathcal{O}(k)\) |
set#
| operation | time complexity |
|---|
my_set.add(item) | \(\mathcal{O}(1)\) |
my_set.remove(item) | \(\mathcal{O}(1)\) |
item in my_set | \(\mathcal{O}(1)\) |
for item in my_set | \(\mathcal{O}(n)\) |
set1 & set2 | \(\mathcal{O}(n)\) |
set1 | set2 | \(\mathcal{O}(n)\) |
set1 ^ set2 | \(\mathcal{O}(n)\) |
set1 - set2 | \(\mathcal{O}(n)\) |
counter#
| operation | time complexity |
|---|
counter[item] | \(\mathcal{O}(1)\) |
counter.pop(item) | \(\mathcal{O}(1)\) |
for k, v in counter.items(): | \(\mathcal{O}(n)\) |
for k, v in counter.most_common(): | \(\mathcal{O}(n\log(n))\) |
for k, v in counter.most_common(k): | \(\mathcal{O}(n \log(k))\) |
counter.update(iterable) | \(\mathcal{O}(k)\) |
counter.subtract(iterable) | \(\mathcal{O}(k)\) |
counter.total() | \(\mathcal{O}(n)\) |
heap / priority queue#
| operation | time complexity |
|---|
heapq.heapify(sequence) | \(\mathcal{O}(n)\) |
heapq.heappop(sequence) | \(\mathcal{O}(\log(n))\) |
heapq.heappush(sequence, item) | \(\mathcal{O}(\log(n))\) |
sequence[0] | \(\mathcal{O}(1)\) |
sorted list#
| operation | time complexity |
|---|
sorted_sequence = sorted(sequence) | \(\mathcal{O}(n\log(n))\) |
sorted_sequence.index(item) | \(\mathcal{O}(n)\) |
bisect.bisect(sorted_sequence, item) | \(\mathcal{O}(\log(n))\) |
bisect.insort(sorted_sequence, item) | \(\mathcal{O}(n)\) |
general traversals:#
| operation | time complexity |
|---|
min(iterable) | \(\mathcal{O}(n)\) |
max(iterable) | \(\mathcal{O}(n)\) |
sorted(iterable) | \(\mathcal{O}(n\log(n))\) |
heapq.nsmallest(k, iterable) | \(\mathcal{O}(n\log(k))\) |
statistics.multimode(iterable) | \(\mathcal{O}(n)\) |
Operations (and their return types)#
Many of the operations have been enumerated in the previous section on Time Complexities, but operations such as .values() on a dict, have not been discussed. This section will aggregate that information.
dict views#
The view objects are dynamic — they reflect mutations to the underlying dict.
| operation | returns | notes |
|---|
d.keys() | dict_keys | set-like view of keys |
d.values() | dict_values | view of values (not set-like — may dupe) |
d.items() | dict_items | set-like view of (key, value) tuples |
d.copy() | dict | shallow copy |
dict.fromkeys(it, v) | dict | new dict with keys from it mapped to v |
list mutation#
In-place mutators on list return None — chaining lst.sort().reverse() is a common bug.
| operation | returns | notes |
|---|
lst.sort(key=fn, reverse=True) | None | stable, in-place |
lst.reverse() | None | in-place |
lst.copy() | list | shallow copy (same as lst[:]) |
lst.clear() | None | empties in place |
sorted(lst, key=fn) | list | non-mutating; returns new list |
reversed(lst) | list_reverseiterator | lazy iterator |
set algebra#
Each of the named methods has an operator counterpart that requires both sides to be sets; the methods accept any iterable.
| operation | returns | symbol |
|---|
a.union(b) | set | a | b |
a.intersection(b) | set | a & b |
a.difference(b) | set | a - b |
a.symmetric_difference(b) | set | a ^ b |
a.issubset(b) | bool | a <= b |
a.issuperset(b) | bool | a >= b |
a.isdisjoint(b) | bool | — |
string essentials#
str is immutable — every method returns a new string.
| operation | returns | notes |
|---|
s.split(sep) | list | splits on whitespace if sep omitted |
sep.join(iterable) | str | iterable must contain strings |
s.strip() | str | also lstrip, rstrip |
s.replace(a, b) | str | replaces all (or first n) |
s.startswith(p) | bool | p may be a tuple of prefixes |
s.endswith(p) | bool | suffix variant of the above |
s.find(sub) | int | -1 if absent (vs index which raises) |
s.format(*args, **kw) | str | f-strings preferred for literals |
s.encode(“utf-8”) | bytes | inverse of bytes.decode |
numeric & iterator built-ins#
| operation | returns | notes |
|---|
abs(x) | same numeric type | also magnitude for complex |
round(x, ndigits) | int / float | banker’s rounding |
divmod(a, b) | tuple | (a // b, a % b) |
enumerate(it, start=0) | enumerate | yields (i, item) |
zip(*iters, strict=False) | zip | strict=True raises on mismatch (3.10+) |
map(fn, *iters) | map | lazy |
filter(fn, it) | filter | lazy; None keeps truthy |
any(it) / all(it) | bool | short-circuit |
sum(it, start=0) | numeric | math.fsum for floats |
REPL#
Read-Eval-Print Loop — Python’s interactive interpreter. Launch with python (or python -i script.py to run a script and then drop into a REPL with its globals already populated).
the underscore variable#
In interactive mode, is bound to the value of the last expression that wasn’t None. Successive underscores and hold the previous two — useful for chaining when you forgot to assign:
>>> 2 + 2
4
>>> _ * 10
40
>>> _ + __
44
This binding is REPL-only. Inside a script, _ is just the conventional name for “I don’t care about this value” (e.g. for _ in range(n):).
introspection#
| operation | description |
|---|
help(obj) | interactive help / docstring |
dir(obj) | list attributes (filter with _-prefix to drop dunders) |
type(obj) | runtime type |
vars(obj) | the dict of obj |
repr(obj) | unambiguous string form (what the REPL prints) |
id(obj) | CPython memory address — identity, not equality |
obj? | IPython-only: docstring + signature |
obj?? | IPython-only: full source |
invocation flags#
| command | effect |
|---|
python -i script.py | run the script\, then drop into the REPL with its namespace |
python -m module | run a module as a script (e.g. python -m http.server, python -m json.tool, python -m venv .venv) |
python -c “code” | execute a one-liner |
python -O | strip assert and skip debug branches |
environment#
PYTHONSTARTUP: path to a file run on every interactive REPL start — handy for default imports or aliases.PYTHONDONTWRITEBYTECODE=1: suppress pycache when fiddling with throwaway scripts.PYTHONBREAKPOINT: overrides what breakpoint() drops into (default pdb.set_trace; set to ipdb.set_trace for richer debugging or 0 to disable).- exit with
exit(), quit(), or Ctrl-D (Ctrl-Z Enter on Windows).
alternatives#
- IPython —
?/?? introspection, magic commands (%timeit, %run, %load_ext autoreload; full list via %lsmagic), better tracebacks. - ptpython — multiline editing, syntax highlighting, inline type hints.
- bpython — minimal cousin of IPython with autocomplete and rewind.
- python -m asyncio (3.8+) — REPL with top-level
await for coroutine experimentation.