Python Cheatsheet#
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()
|
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#