Python Essentials¶
The Python you need every day for data science and AI work: variables, built-in types, control flow, functions, comprehensions, generators, exceptions, files, modules, and decorators.
Table of Contents¶
- Installation / Setup
- Core Syntax
- Common Operations
- Practical Examples
- Common Patterns
- Best Practices
- Common Mistakes
- Troubleshooting
- Related Cheat Sheets
- Official Documentation
Installation / Setup¶
Python 3.10+ is recommended for data science (3.12 is current). Manage environments with virtual environments and uv or pip.
python --version # check version
python script.py # run a script
python -c "print(1+1)" # run a one-liner
python # start the REPL
| Setup task | Command |
|---|---|
| Install packages | pip install pandas numpy or uv add pandas numpy |
| Notebooks | pip install jupyter → jupyter lab |
| Interactive data exploration | pip install ipython → ipython |
Core Syntax¶
Variables¶
Dynamic typing with snake_case names. No declaration needed.
Data types¶
| Type | Example | Notes |
|---|---|---|
int |
42, -7 |
Arbitrary precision |
float |
3.14, 1e-5 |
IEEE-754 double |
bool |
True, False |
Subclass of int |
str |
"hi" |
Immutable, Unicode |
bytes |
b"hi" |
Raw bytes |
list |
[1, 2] |
Mutable, ordered |
tuple |
(1, 2) |
Immutable, ordered |
set |
{1, 2} |
Unique, unordered |
dict |
{"a": 1} |
Key → value |
NoneType |
None |
"No value" |
Operators¶
| Category | Operators |
|---|---|
| Arithmetic | + - * / // % ** |
| Comparison | == != < > <= >= |
| Logical | and or not |
| Identity | is is not |
| Membership | in not in |
| Assignment | = += -= *= /= //= %= **= |
| Bitwise | & \| ^ ~ << >> |
7 // 2 == 3 # floor division
7 % 2 == 1 # modulo (remainder)
2 ** 10 == 1024 # power
[1, 2] + [3] # [1, 2, 3] concatenation
3 in [1, 2, 3] # True membership
Strings¶
name = "Ada"
f"Hi {name}, score: {0.934:.2f}" # f-strings: preferred formatting
name.upper() # 'ADA'
"a,b,c".split(",") # ['a', 'b', 'c']
" ".join(["a", "b"]) # 'a b'
" x ".strip() # 'x'
"hi".replace("i", "ello") # 'hello'
"file.csv".endswith(".csv") # True
r"\d+" # raw string: no escape processing
Lists, tuples, sets, dicts¶
xs = [3, 1, 2]
xs.append(4) # [3, 1, 2, 4]
xs[0] # 3
xs[-1] # 4 (last element)
xs[1:3] # [1, 2] slice
xs.sort() # in-place; sorted(xs) returns new
xs.pop() # remove & return last
t = (1, 2, 3) # tuple: immutable
a, b, c = t # unpacking
s = {1, 2, 2, 3} # {1, 2, 3} — duplicates removed
{1, 2} & {2, 3} # {2} intersection
{1, 2} | {2, 3} # {1, 2, 3} union
{1, 2} - {2} # {1} difference
d = {"a": 1, "b": 2}
d["c"] = 3 # add / update
d.get("z", 0) # 0 — no KeyError
d.setdefault("k", []) # set default if missing
list(d.items()) # [('a', 1), ...]
"a" in d # True membership on keys
Conditions¶
if x > 0:
...
elif x == 0:
...
else:
...
"adult" if age >= 18 else "minor" # ternary
match status: # structural pattern matching (3.10+)
case 200:
print("ok")
case 404 | 500:
print("error")
case _:
print("other")
Truthiness: 0, "", [], {}, set(), None are falsy; everything else is truthy.
Loops¶
for i in range(5): # 0..4
...
for i, row in enumerate(rows): # index + value
...
for a, b in zip(xs, ys): # pair up iterables
...
while x < 10:
x += 1
if x == 5:
break # exit loop
else:
print("no break hit") # runs only if no break
Common Operations¶
Comprehensions¶
[x ** 2 for x in range(5)] # [0, 1, 4, 9, 16]
[x for x in nums if x > 0] # filter
{k: v * 2 for k, v in d.items()} # dict comprehension
{x % 3 for x in nums} # set comprehension
(x for x in nums) # generator expression (lazy!)
Functions¶
def score(y_true, y_pred, *, verbose=False): # * = keyword-only after it
"""Compute accuracy."""
return sum(a == b for a, b in zip(y_true, y_pred)) / len(y_true)
def f(a, b=10, *args, **kwargs): # defaults, varargs, keywords
...
- Positional defaults must come before
*args;**kwargscaptures named extras. - Functions are first-class: store, pass, and return them.
- Lambdas for short inline functions:
sorted(items, key=lambda x: x["age"]).
Iterators & generators¶
it = iter([1, 2, 3])
next(it) # 1; raises StopIteration when exhausted
def read_chunks(path, size=1024): # generator: lazy, memory-friendly
with open(path) as f:
while chunk := f.read(size):
yield chunk
sum(x for x in range(1_000_000)) # generator expression: no giant list
Exceptions¶
try:
result = risky_operation()
except ValueError as e:
print("bad value:", e)
except (TypeError, KeyError):
print("type or key problem")
else:
print("no error — use result here")
finally:
cleanup() # always runs
raise ValueError("invalid input") # raise your own
Files¶
with open("data.csv", encoding="utf-8") as f: # with = auto-close
for line in f:
...
# Pathlib is the modern way (see python-standard-library.md)
from pathlib import Path
text = Path("data.csv").read_text(encoding="utf-8")
Path("out").mkdir(exist_ok=True)
| Mode | Meaning |
|---|---|
"r" |
Read (default) |
"w" |
Write (truncates) |
"a" |
Append |
"rb" / "wb" |
Binary read / write |
Modules & packages¶
import numpy as np # alias
from sklearn.model_selection import train_test_split
from package.module import thing # package = dir with __init__.py
if __name__ == "__main__": # runs only when executed directly
main()
Decorators¶
import functools
def timer(func):
@functools.wraps(func) # preserve name/docstring
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
print(f"{func.__name__}: {time.perf_counter() - start:.4f}s")
return result
return wrapper
@timer
def train(model): ...
Built-in decorators: @staticmethod, @classmethod, @property, @dataclass, @functools.lru_cache, @contextlib.contextmanager (see OOP and standard library).
Context managers¶
with open(...) as f: ... # resource auto-released
with np.errstate(divide="ignore"): ... # NumPy warning control
from contextlib import contextmanager
@contextmanager
def session():
print("open")
try:
yield
finally:
print("close")
Practical Examples¶
1. Compute summary stats from a CSV-like file¶
import csv
from collections import Counter
with open("sales.csv", newline="", encoding="utf-8") as f:
rows = list(csv.DictReader(f))
total = sum(float(r["amount"]) for r in rows)
by_region = Counter(r["region"] for r in rows)
print(total, by_region.most_common(3))
2. Filter and rank records¶
users = [
{"name": "Ada", "score": 92},
{"name": "Lin", "score": 85},
{"name": "Sam", "score": 78},
]
top = [u for u in sorted(users, key=lambda u: u["score"], reverse=True) if u["score"] >= 80]
3. Stream a large file in chunks¶
def rows(path, batch=1000):
buffer = []
with open(path, encoding="utf-8") as f:
for line in f:
buffer.append(line.strip())
if len(buffer) >= batch:
yield buffer
buffer = []
if buffer:
yield buffer
Common Patterns¶
# Default-argument idiom (never use mutable defaults directly)
def add(x, seen=None):
seen = [] if seen is None else seen
...
# Dict lookups with defaults
counts = {}
counts[word] = counts.get(word, 0) + 1
# any / all for bulk checks
all(x > 0 for x in nums)
any(row["status"] == "failed" for row in rows)
# min / max with key
cheapest = min(items, key=lambda i: i["price"])
# Swap / unpack
a, b = b, a
first, *rest, last = xs
Best Practices¶
- Follow PEP 8:
snake_casenames, 4-space indentation, blank lines between functions. - Prefer f-strings over
%formatting and.format(). - Use
withfor files and resources — never open without closing. - Prefer generators over lists for large data (memory).
- Write type hints on public functions — see python-typing.md.
- Keep functions small and single-purpose; one function = one job.
- Use
pathlibinstead of string path manipulation. - Always work inside a virtual environment for projects.
Common Mistakes¶
| Mistake | Consequence | Correct approach |
|---|---|---|
| Mutable default argument | State leaks across calls | Default to None, create inside |
== vs is |
is compares identity, not value |
== for values; is None for None |
| Modifying a list while iterating | Skipped / repeated items | Iterate over a copy: for x in xs[:] |
xs = ys then mutate |
Both variables change | xs = ys.copy() or copy.deepcopy |
String + in a loop |
O(n²) — slow on large data | "".join(parts) |
Shadowing builtins (list, dict, sum) |
Confusing bugs | Rename: rows, data, total |
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
ModuleNotFoundError: No module named 'pandas' |
Package not installed / wrong environment | pip install pandas; check active venv |
IndentationError |
Mixed tabs/spaces | Use 4 spaces consistently |
UnboundLocalError: local variable 'x' referenced... |
Assigned inside function shadows outer | Use global/nonlocal or rename |
TypeError: 'int' object is not subscriptable |
Indexing a non-sequence | Check the value's actual type |
StopIteration |
next() on exhausted iterator |
Catch it or use next(it, default) |
FileNotFoundError |
Path wrong or relative to wrong cwd | Use Path(__file__).parent for project-relative paths |
Related Cheat Sheets¶
- Python OOP — classes, inheritance, dataclasses
- Python Standard Library —
os,pathlib,json,collections,itertools - Python Regex — text pattern matching with
re - Python Typing — type hints and static checking
- Virtual Environments · pip · uv — environment & packaging
- Data Analysis — pandas and NumPy build on this sheet
- Home · Central Navigation Index
Official Documentation¶
Last Updated¶
2026-09-06 — Initial version.