Python Cheatsheet

pep8 = bible

Numerical Work: Use NumPy by Default

For this course, use NumPy for most numerical calculations.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import numpy as np

np.sqrt(9)           # → 3.0
np.sqrt(-1 + 0j)     # → 1j; use complex input
np.pi
np.exp(1)
np.log(10)           # natural logarithm
np.sin(np.pi / 2)

# The same functions work element-wise on arrays
x = np.array([1.0, 4.0, 9.0])
np.sqrt(x)           # → array([1., 2., 3.])

You generally won’t need the math or cmath modules in this course.


REPL & Package Management

Python’s standard REPL has no separate package or shell modes.

Where Command Purpose
Terminal python Start Python
Python help(str) Documentation
Python dir(str) List attributes and methods
Python exit() Exit
Terminal python script.py Run a file
Terminal python -m pip install numpy Install a package
Terminal python -m pip list List installed packages
Terminal python -m pip uninstall numpy Remove a package

On some systems, use python3 instead of python.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Create a project environment
python -m venv .venv

# Activate: macOS / Linux
source .venv/bin/activate

# Activate: Windows PowerShell
.venv\Scripts\Activate.ps1

# Install packages used below
python -m pip install numpy pandas matplotlib

# Deactivate the environment
deactivate

Variables & Types

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
x = 55699             # int
x = 1 + 1j            # complex
x = 3.14              # float
x = True              # bool: True / False
x = None              # absence of a value

type(x)               # check type
isinstance(x, float)  # check whether x is a float

int("42")             # string → integer
float("3.14")         # string → float
str(42)               # integer → string

For NumPy arrays:

1
2
3
4
5
6
7
import numpy as np

v = np.array([1, 2, 3], dtype=float)
v.dtype               # element type
v.shape               # → (3,)
v.ndim                # number of dimensions → 1
v.size                # total element count → 3

Arithmetic & Math

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import numpy as np

2 ** 3                # exponent → 8 (not ^)
8 / 5                 # true division → 1.6
8 // 5                # floor division → 1
-8 // 5               # → -2: rounds down
8 % 5                 # modulo → 3

np.sqrt(9)            # → 3.0
np.sqrt(-1 + 0j)      # → 1j
abs(-3)               # → 3
np.abs(-3)            # also works on arrays
round(3.14159, 2)     # → 3.14

np.pi
np.exp(1)
np.log(10)            # natural logarithm
np.log10(100)         # → 2.0
np.sin(np.pi / 2)
np.cos(0)

# Comparisons and logic for individual values
x = 3
y = 5

x == y                # equality
x != y                # inequality
x > 0 and x < 10
0 < x < 10            # chained comparison
x < 0 or x > 10
not True              # → False
x is None             # identity check for None

For NumPy arrays, use element-wise logical operators:

1
2
3
4
5
6
7
8
v = np.array([-1, 2, 12])

(v > 0) & (v < 10)   # element-wise AND
(v < 0) | (v > 10)   # element-wise OR
~(v > 0)              # element-wise NOT

np.any(v > 0)         # is at least one element positive?
np.all(v > 0)         # are all elements positive?

Use parentheses around each comparison when combining conditions with & or |.


Strings

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
s = "hello"

f"{s} world"          # interpolation
s + "!"               # concatenation
len(s)
s.upper()
"a b c".split()       # → ["a", "b", "c"]
", ".join(["a", "b"]) # → "a, b"
"  hello  ".strip()   # → "hello"
s.replace("h", "H")

s[0]                  # first character
s[-1]                 # last character
s[1:4]                # → "ell"; stop index excluded

f"{3.14159:.2f}"      # → "3.14"

Strings are immutable: s[0] = "H" raises an error.


Functions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Anonymous function: a single expression
double = lambda x: 2 * x

# Full form: preferred for non-trivial logic
def square(x):
    return x ** 2

square(2)             # → 4

# Optional positional arguments + keyword-only arguments
def f(x, y=2, z=3, *, a=4.0, b=5.0):
    print([x, y, z, a, b])
    return x + y + z ** a + b

f(1)
f(1, 10, b=173, a=77)
f(1, 2, 4, b=173)

# Unpack a dictionary as keyword arguments
opts = {"a": 5.0, "b": 3.0}
f(1, 2, 4, **opts)

# Unpack positional arguments
args = (1, 2, 4)
f(*args, **opts)

# Accept any number of positional arguments
def total(*values):
    return sum(values)

total(1, 2, 3)        # → 6

# Type hints: documentation, not runtime enforcement
def cube(x: float) -> float:
    return x ** 3

Indentation defines blocks—normally four spaces. There is no end.

Avoid mutable defaults such as items=[]; use None and create the list inside the function.

Element-wise functions

1
2
3
4
5
6
7
import numpy as np

v = np.array([1.0, 2.0, 3.0])

square(v)             # works because NumPy supports v ** 2
np.sin(v)             # element-wise sine
np.sin(v) ** 2

A function works on arrays directly only if its operations support arrays. Otherwise, use a comprehension:

1
results = [f(x) for x in v]

Control Flow

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
x = 3

if x > 0:
    print("positive")
elif x == 0:
    print("zero")
else:
    print("negative")

# Conditional expression
label = "pos" if x > 0 else "non-pos"

# for loop: stop value excluded
for i in range(1, 6):
    print(i)           # 1 through 5

# while loop
i = 1
while i <= 5:
    i += 1

# break / continue
for i in range(10):
    if i == 2:
        continue
    if i == 5:
        break

# Error handling
try:
    n = int("hello")
except ValueError:
    print("Not an integer")

Lists, Tuples, Dictionaries & Sets

Lists

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# List: mutable sequence
v = [1, 2, 3]

v.append(4)           # append one value
v.extend([5, 6])      # append multiple values
last = v.pop()        # remove and return last value

len(v)
sum(v)
max(v)
min(v)

sorted(v)            # return a sorted copy
v.sort()             # sort in place; returns None

# Concatenation
[1, 2] + [3, 4]      # → [1, 2, 3, 4]

# Indexing: zero-based; slice stop excluded
v[0]                 # first element
v[-1]                # last element
v[1:4]               # elements at indices 1, 2, 3
v[1:]                # from second element onward
v[::2]               # every second element
v[::-1]              # reversed copy

Use NumPy arrays for numerical arithmetic. Lists behave differently:

1
2
[1, 2] * 2                      # → [1, 2, 1, 2]
np.array([1, 2]) * 2            # → array([2, 4])

Tuples, dictionaries & sets

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# Tuple: immutable sequence
point = (2, 3)
x, y = point         # unpacking
single = (2,)        # one-element tuple needs a comma

# Dictionary: key → value
params = {"a": 4.0, "b": 5.0}

params["a"]
params["c"] = 6.0
params.get("missing", 0)

for key, value in params.items():
    print(key, value)

# Set: unique elements
values = {1, 2, 2, 3} # → {1, 2, 3}
values.add(4)
2 in values          # → True
empty_set = set()    # {} creates an empty dictionary

Ranges, comprehensions & iteration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
r = range(1, 11)     # lazy range: 1 through 10
range(0, 10, 2)      # 0, 2, 4, 6, 8

arr = [x ** 2 for x in range(1, 11)]
gen = (x ** 2 for x in range(1, 11))  # lazy generator
list(gen)            # materialize; consumes the generator

evens = [x for x in range(10) if x % 2 == 0]

# Iterate over values directly
v = [1, 2, 3]

for value in v:
    print(value)

# Index and value
for i, value in enumerate(v):
    print(f"v[{i}] = {value}")

# Iterate two sequences together
w = [10, 20, 30]

for a, b in zip(v, w):
    print(a + b)      # zip stops at the shorter sequence

Numerical Arrays — NumPy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import numpy as np

v = np.array([1, 2, 3], dtype=float)

# Constructors
np.zeros(3)
np.ones(3)
np.full(3, np.pi)
np.empty(3)           # uninitialized values

# Random numbers
rng = np.random.default_rng(42)  # seed for reproducibility
rng.random(5)         # uniform [0, 1)
rng.standard_normal(5)

# Ranges
np.arange(1, 11)      # 1 through 10
np.arange(0, 1, 0.1)  # stop excluded; floating-point steps
np.linspace(0, 1, 50) # 50 points, both endpoints included

# Element-wise arithmetic
v ** 2
np.sin(v) ** 4
v + 10
v * v

# Reductions
v.sum()
v.prod()
v.max()
v.min()
v.mean()
v.std()               # population standard deviation by default

# Indexing
v[0]                  # first element
v[-1]                 # last element
v[1:3]                # second and third elements

# Filtering
v[v > 1]

# Modify in place
v *= 2
v.fill(np.pi)

Copies & views

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
v = np.array([1.0, 2.0, 3.0])

# Basic slices usually share the original data
part = v[1:]
part[0] = 99          # also changes v

# Explicit independent copy
independent = v[1:].copy()

# Assignment shares the same object
alias = v
independent = v.copy()

Matrices — NumPy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import numpy as np

A = np.array([[1, 2, 3],
              [4, 5, 6]])       # shape (2, 3)

# Reshape: default order fills rows first
np.arange(1, 10).reshape(3, 3)

# Julia-style column-first order
np.arange(1, 10).reshape(3, 3, order="F")

# Constructors
np.zeros((3, 3))
np.ones((2, 4))
np.empty((3, 3))                # uninitialized values
np.eye(3)                       # identity matrix

rng = np.random.default_rng(42)
rng.random((3, 3))
rng.standard_normal((3, 3))

# Indexing: zero-based
A[0, 1]                         # first row, second column
A[:, 0]                         # first column
A[0, :]                         # first row

# Row / column arrays
v = np.array([1, 2, 3])
row = v[None, :]                # shape (1, 3)
col = v[:, None]                # shape (3, 1)

# Transposing a 1D array does not make it a column
v.T.shape                       # still (3,)

# Concatenation
np.vstack((A, A))               # stack rows
np.hstack((A, A))               # join columns

# Transpose
A.T                             # ordinary transpose
A.conj().T                      # conjugate transpose

Linear algebra

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
A = np.array([[3.0, 1.0],
              [1.0, 2.0]])
B = np.eye(2)
b = np.array([9.0, 8.0])

A @ B                           # matrix multiplication
A * B                           # element-wise multiplication

np.linalg.inv(A)
np.trace(A)
np.diag(A)
np.linalg.det(A)
np.linalg.norm(A)

values, vectors = np.linalg.eig(A)
np.linalg.eigvals(A)
U, s, Vh = np.linalg.svd(A)

# Solve A @ x = b
x = np.linalg.solve(A, b)        # prefer over inv(A) @ b

Broadcasting

1
2
3
4
5
6
A = np.ones((2, 3))
v = np.array([10, 20, 30])

A + v                           # adds v to every row
A.sum(axis=0)                   # sum over rows → shape (3,)
A.sum(axis=1)                   # sum over columns → shape (2,)

Dimensions are compatible when they match or one is 1, comparing from the right.


Summation Patterns

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import numpy as np

N = 10

# Loop
result = 0.0
for i in range(1, N + 1):
    result += 1 / i ** 2

# List comprehension
result = sum([1 / i ** 2 for i in range(1, N + 1)])

# Generator: no intermediate list
result = sum(1 / i ** 2 for i in range(1, N + 1))

# NumPy: convenient for numerical arrays
i = np.arange(1, N + 1, dtype=float)
result = np.sum(1 / i ** 2)

Recursion

1
2
3
4
5
6
def fac(n: int) -> int:
    if n < 0:
        raise ValueError("n must be non-negative")
    return 1 if n == 0 else n * fac(n - 1)

fac(5)                          # → 120

This function expects a non-negative integer. Type hints do not validate inputs at runtime.

Python limits recursion depth; use loops or library functions for large inputs.


I/O

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# User input
s = input("Text: ")
x = float(input("Number: "))
n = int(input("Integer: "))

# Output
print("hello")
print(f"x = {x:.3f}")

# "w" overwrites; with closes the file automatically
with open("notes.txt", "w", encoding="utf-8") as file:
    file.write("hello\n")

with open("notes.txt", encoding="utf-8") as file:
    text = file.read()

Numerical text files

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import numpy as np

# Example: solver returns two real numbers per x
def solver(x):
    return np.sin(x), np.cos(x)

x_arr = np.linspace(0, 1, 10)

# Rows = samples; columns = x plus two solver outputs
data = np.zeros((len(x_arr), 3))

for i, x_now in enumerate(x_arr):
    data[i, :] = [x_now, *solver(x_now)]

# Header automatically starts with "# "
np.savetxt("result.dat", data, delimiter="\t", header="x\ty\tz")

data2 = np.loadtxt("result.dat", delimiter="\t", comments="#")
xvec = data2[:, 0]
yvec = data2[:, 1]
zvec = data2[:, 2]

# Alternative: calculate all samples at once
yvec, zvec = solver(x_arr)
data = np.column_stack((x_arr, yvec, zvec))

CSV & DataFrames — pandas

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd

# Named columns in an ordinary CSV
df = pd.DataFrame({"x": xvec, "y": yvec, "z": zvec})
df.to_csv("result.csv", index=False)

df2 = pd.read_csv("result.csv")

# Read the tab-delimited file above
df3 = pd.read_csv(
    "result.dat",
    sep="\t",
    comment="#",
    header=None,
    names=["x", "y", "z"],
)

df["x"]                         # one column
df.head()                       # first five rows
df["x"].to_numpy()              # column → NumPy array

Load another Python file

1
2
3
4
5
6
7
# For a local file named myfile.py
import myfile
from myfile import solver

# Code that runs only when this file is executed directly
if __name__ == "__main__":
    print("Running as a script")

Plotting — Matplotlib

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 200)

fig, ax = plt.subplots()
ax.plot(x, np.sin(x), label="sin(x)", linewidth=2)
ax.plot(x, np.cos(x), label="cos(x)", linestyle="--")

ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_title("Trig functions")
ax.legend()

fig.tight_layout()
fig.savefig("fig.png", dpi=300)  # also .pdf or .svg
plt.show()

Introspection & Performance

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import inspect
import timeit
import cProfile
import dis

def square(x):
    return x ** 2

help(square)
dir(square)
inspect.signature(square)
inspect.getsource(square)      # requires available source
dis.dis(square)                # Python bytecode

# Average time per call across 10,000 calls
elapsed = timeit.timeit(lambda: square(10), number=10_000)
print(elapsed / 10_000)

# Profile a workload
cProfile.run("sum(i ** 2 for i in range(100_000))")

In IPython / Jupyter only:

1
2
3
4
5
square?                        # help
square??                       # source, when available
%timeit square(10)             # repeated timing
%run script.py                 # run a script
%pip install numpy             # install into current environment

Key Differences from Julia

Julia Python
true, false, nothing True, False, None
x^2 x ** 2
1im 1j
First index: 1 First index: 0
1:5 includes 5 range(1, 6) includes 5
v[end] v[-1]
length(v) len(v)
push!(v, x) v.append(x) for a list
f.(v) Array-compatible function or comprehension
A * B matrix product A @ B for NumPy arrays
A .* B A * B for NumPy arrays
A' A.conj().T
A \ b np.linalg.solve(A, b)
using Foo import foo
Blocks end with end Blocks use indentation

Remember: Python slices exclude the stop index, and basic NumPy slices usually return views that share the original data.


Further Resources