The Python syntax you forget between projects — and the patterns you need every day. This reference covers everything from data types to OOP, comprehensions, file I/O, and the standard library.
Quick reference
The 25 patterns that cover 90% of daily Python work.
| Pattern | Example |
|---|---|
| f-string | f"Hello, {name}!" |
| List comprehension | [x*2 for x in range(10)] |
| Dict comprehension | {k: v for k, v in pairs} |
| Unpack list | a, *rest = [1, 2, 3, 4] |
| Swap variables | a, b = b, a |
| Ternary | x if condition else y |
| Walrus operator | if n := len(data): |
| Default arg | def fn(x, y=10): |
*args / **kwargs |
def fn(*args, **kwargs): |
| Enumerate | for i, v in enumerate(lst): |
| Zip | for a, b in zip(lst1, lst2): |
| Sort by key | sorted(lst, key=lambda x: x.age) |
| Dict get with default | d.get("key", "fallback") |
| Set operations | a & b, `a |
| List slicing | lst[1:4], lst[::-1] |
| String join | ", ".join(["a", "b", "c"]) |
| Any / All | any(x > 0 for x in lst) |
| Open file | with open("f.txt") as fh: |
| JSON parse | json.loads(text) |
| Path join | Path("dir") / "file.txt" |
| Regex match | re.search(r"\d+", text) |
| Dataclass | @dataclass class Point: x: float |
| Context manager | with open(...) as f: |
| Try / except | try: ... except ValueError as e: |
| Type hint | def fn(x: int) -> str: |
Data types
# Strings (immutable)
s = "hello"
s = 'world'
s = """multiline
string"""
# Numbers
n = 42 # int
f = 3.14 # float
c = 1 + 2j # complex
b = 0b1010 # binary → 10
o = 0o17 # octal → 15
h = 0xFF # hex → 255
# Booleans
True False # note: capital
# None
x = None
# Type checking
type(42) # <class 'int'>
isinstance(42, int) # True
# Type conversion
int("42") # 42
float("3.14") # 3.14
str(42) # "42"
bool(0) # False
list("abc") # ['a', 'b', 'c']
Strings
s = "Hello, World!"
# Access
s[0] # 'H'
s[-1] # '!'
s[7:12] # 'World'
s[::-1] # '!dlroW ,olleH'
# Common methods
s.upper() # 'HELLO, WORLD!'
s.lower() # 'hello, world!'
s.strip() # remove whitespace
s.lstrip("H") # remove leading 'H'
s.split(", ") # ['Hello', 'World!']
s.replace("World", "Python")
s.startswith("Hello") # True
s.endswith("!") # True
s.find("World") # 7 (-1 if not found)
s.count("l") # 3
s.zfill(5) # zero-pad to width 5
s.center(20, "-") # '--Hello, World!--'
# Check type
s.isdigit() s.isalpha() s.isalnum()
# f-strings (Python 3.6+)
name = "Ana"
age = 30
f"Hello, {name}! You are {age}."
f"{age:.2f}" # 2 decimal places
f"{age:05d}" # zero-padded int
f"{name!r}" # repr of name
f"{1_000_000:,}" # '1,000,000'
# Multiline and raw strings
path = r"C:\Users\name" # raw: backslash literal
text = (
"Line one "
"line two" # implicit concatenation
)
# join
", ".join(["a", "b", "c"]) # 'a, b, c'
# format() (older style)
"{} is {}".format("Python", "great")
"{name}".format(name="Python")
Lists
lst = [1, 2, 3, 4, 5]
# Access / slice
lst[0] # 1
lst[-1] # 5
lst[1:3] # [2, 3]
lst[::2] # [1, 3, 5]
# Modify
lst.append(6) # add to end
lst.insert(0, 0) # insert at index
lst.extend([7, 8]) # add multiple
lst.remove(3) # remove first match
lst.pop() # remove and return last
lst.pop(0) # remove and return index 0
lst.clear() # empty list
# Info
len(lst) # length
lst.count(2) # occurrences
lst.index(4) # first index
# Sort
lst.sort() # in-place, ascending
lst.sort(reverse=True) # in-place, descending
lst.sort(key=lambda x: x.name) # by attribute
sorted(lst) # returns new list
lst.reverse() # in-place reverse
# Copy (shallow)
copy = lst.copy()
copy = lst[:]
# Comprehensions
squares = [x**2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
flat = [x for row in matrix for x in row]
# Unpack
a, b, c = [1, 2, 3]
a, *rest = [1, 2, 3, 4] # rest = [2, 3, 4]
*init, last = [1, 2, 3, 4] # init = [1, 2, 3]
# Stack and queue
stack = []
stack.append(x) # push
stack.pop() # pop from top
from collections import deque
q = deque()
q.append(x) # enqueue
q.popleft() # dequeue
Dictionaries
d = {"name": "Ana", "age": 30}
# Access
d["name"] # 'Ana' — KeyError if missing
d.get("name") # 'Ana' — None if missing
d.get("city", "N/A") # 'N/A' (default)
# Modify
d["email"] = "a@b.com" # add / update
del d["age"] # remove key
d.pop("age", None) # remove, return value (no error)
d.update({"city": "PG"}) # merge in-place
# Iterate
for key in d: # keys
for val in d.values():
for k, v in d.items():
# Info
"name" in d # True
len(d) # 2
list(d.keys())
list(d.values())
# Merge (Python 3.9+)
merged = d1 | d2 # new dict
d1 |= d2 # in-place
# Dict comprehension
sq = {x: x**2 for x in range(5)}
# setdefault
d.setdefault("score", 0) # set if key absent, return value
# defaultdict
from collections import defaultdict
counter = defaultdict(int)
counter["a"] += 1 # no KeyError
# Counter
from collections import Counter
c = Counter(["a", "b", "a", "c", "a"])
c.most_common(2) # [('a', 3), ('b', 1)]
Sets
s = {1, 2, 3}
s = set() # empty (not {})
s.add(4)
s.remove(2) # KeyError if absent
s.discard(2) # no error if absent
# Set operations
a = {1, 2, 3}
b = {2, 3, 4}
a | b # union {1, 2, 3, 4}
a & b # intersection {2, 3}
a - b # difference {1}
a ^ b # symmetric difference {1, 4}
a.issubset(b)
a.issuperset(b)
a.isdisjoint(b)
# Deduplicate a list (order not preserved)
unique = list(set(lst))
Tuples
t = (1, 2, 3)
t = 1, 2, 3 # parens optional
t = (42,) # single-element tuple (note comma)
# Unpack
x, y, z = t
x, *rest = t
# Named tuple
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(1, 2)
p.x # 1
Control flow
# if / elif / else
if x > 0:
print("positive")
elif x < 0:
print("negative")
else:
print("zero")
# Ternary
label = "even" if x % 2 == 0 else "odd"
# Walrus operator (Python 3.8+)
if (n := len(data)) > 10:
print(f"Too long: {n}")
# for loop
for i in range(5): # 0 1 2 3 4
for i in range(2, 10, 2): # 2 4 6 8
for i, v in enumerate(lst):
for a, b in zip(lst1, lst2):
# while
while condition:
...
# break / continue / else on loop
for x in lst:
if x < 0:
break
if x == 0:
continue
else: # runs if loop completed without break
print("done")
# match (Python 3.10+)
match command:
case "quit":
quit()
case "go" | "move":
move()
case _:
print("unknown")
Functions
# Basic
def greet(name: str) -> str:
return f"Hello, {name}!"
# Default args (mutable defaults are a trap — see mistakes)
def append_to(x, lst=None):
if lst is None:
lst = []
lst.append(x)
return lst
# *args and **kwargs
def variadic(*args, **kwargs):
for arg in args:
print(arg)
for k, v in kwargs.items():
print(f"{k}={v}")
variadic(1, 2, 3, color="red", size=5)
# Keyword-only args (after *)
def fn(a, b, *, verbose=False):
...
# Positional-only args (before /)
def fn(a, b, /, c):
...
# Lambda
double = lambda x: x * 2
sorted(lst, key=lambda x: x["score"])
# Closures
def make_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
# Decorators
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log
def my_func():
...
# Generator
def countdown(n):
while n > 0:
yield n
n -= 1
for x in countdown(5):
print(x)
# Generator expression (memory-efficient)
total = sum(x**2 for x in range(1_000_000))
Classes and OOP
class Animal:
species = "Unknown" # class variable
def __init__(self, name: str, age: int):
self.name = name # instance variable
self.age = age
def speak(self) -> str:
return f"{self.name} says ..."
def __repr__(self) -> str: # for repr()
return f"Animal({self.name!r}, {self.age})"
def __str__(self) -> str: # for print()
return self.name
@classmethod
def create(cls, name: str) -> "Animal":
return cls(name, 0)
@staticmethod
def is_valid_age(age: int) -> bool:
return age >= 0
@property
def info(self) -> str:
return f"{self.name} ({self.age})"
@info.setter
def info(self, value: str):
self.name = value
class Dog(Animal):
def __init__(self, name: str, age: int, breed: str):
super().__init__(name, age)
self.breed = breed
def speak(self) -> str: # override
return f"{self.name} says Woof!"
# Dataclasses (Python 3.7+)
from dataclasses import dataclass, field
@dataclass
class Point:
x: float
y: float
label: str = "origin"
tags: list = field(default_factory=list)
def distance(self) -> float:
return (self.x**2 + self.y**2) ** 0.5
p = Point(3.0, 4.0)
p.distance() # 5.0
# Abstract base class
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self) -> float: ...
class Circle(Shape):
def __init__(self, r: float):
self.r = r
def area(self) -> float:
import math
return math.pi * self.r ** 2
Error handling
# Basic
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Error: {e}")
except (TypeError, ValueError) as e:
print(f"Type or value error: {e}")
except Exception as e:
print(f"Unexpected: {e}")
raise # re-raise
else:
print("No error") # runs if no exception
finally:
print("Always runs") # cleanup here
# Custom exception
class AppError(Exception):
def __init__(self, message: str, code: int = 0):
super().__init__(message)
self.code = code
raise AppError("Not found", code=404)
# Context managers
class ManagedResource:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
# cleanup
return False # don't suppress exceptions
with ManagedResource() as r:
...
# contextlib shortcut
from contextlib import contextmanager
@contextmanager
def timer():
import time
start = time.perf_counter()
yield
print(f"Elapsed: {time.perf_counter() - start:.3f}s")
with timer():
...
File I/O
from pathlib import Path
# Read entire file
text = Path("file.txt").read_text(encoding="utf-8")
data = Path("file.bin").read_bytes()
# Write entire file
Path("out.txt").write_text("hello\n", encoding="utf-8")
# Read line by line (memory-efficient for large files)
with open("file.txt", encoding="utf-8") as fh:
for line in fh:
process(line.rstrip("\n"))
# Write
with open("out.txt", "w", encoding="utf-8") as fh:
fh.write("line one\n")
fh.writelines(["a\n", "b\n"])
# Append
with open("log.txt", "a") as fh:
fh.write("new entry\n")
# CSV
import csv
with open("data.csv", newline="", encoding="utf-8") as fh:
reader = csv.DictReader(fh)
for row in reader:
print(row["name"])
with open("out.csv", "w", newline="", encoding="utf-8") as fh:
writer = csv.DictWriter(fh, fieldnames=["name", "age"])
writer.writeheader()
writer.writerow({"name": "Ana", "age": 30})
# JSON
import json
data = json.loads('{"key": "value"}') # str → dict
text = json.dumps(data, indent=2) # dict → str
json.dump(data, open("out.json", "w")) # dict → file
data = json.load(open("data.json")) # file → dict
# Path operations
p = Path("src") / "data" / "file.txt"
p.exists()
p.is_file()
p.is_dir()
p.suffix # '.txt'
p.stem # 'file'
p.parent # Path('src/data')
p.name # 'file.txt'
p.mkdir(parents=True, exist_ok=True)
list(p.parent.glob("*.txt"))
Useful built-ins
# Iteration helpers
enumerate(lst) # (0, val), (1, val), ...
zip(lst1, lst2) # (a1, b1), (a2, b2), ...
zip(*matrix) # transpose
reversed(lst)
sorted(lst, key=fn, reverse=True)
map(fn, lst) # lazy — wrap in list()
filter(fn, lst) # lazy
# Aggregates
sum([1, 2, 3]) # 6
max([3, 1, 2]) # 3
min([3, 1, 2]) # 1
max(lst, key=lambda x: x.score)
any(x > 0 for x in lst) # True if any match
all(x > 0 for x in lst) # True if all match
# Functional
from functools import reduce
product = reduce(lambda a, b: a * b, [1, 2, 3, 4]) # 24
# Type-related
len(obj)
range(start, stop, step)
abs(-5) # 5
round(3.567, 2) # 3.57
pow(2, 10) # 1024
divmod(17, 5) # (3, 2)
hash("hello")
id(obj)
callable(fn)
# String helpers
repr(obj) # developer-readable
str(obj) # user-readable
chr(65) # 'A'
ord("A") # 65
Common standard library
# os / sys
import os, sys
os.getcwd()
os.environ.get("HOME")
os.listdir(".")
os.path.join("a", "b", "c") # prefer pathlib
sys.argv # command-line args
sys.exit(0)
sys.stdout.write("msg\n")
# datetime
from datetime import datetime, timedelta, timezone
now = datetime.now(tz=timezone.utc)
now.isoformat() # '2026-07-13T...'
datetime.fromisoformat("2026-07-13")
now.strftime("%Y-%m-%d %H:%M:%S")
deadline = now + timedelta(days=7)
(deadline - now).days # 7
# re (regex)
import re
re.search(r"\d+", "abc123") # Match object or None
re.findall(r"\w+", "hello world") # ['hello', 'world']
re.sub(r"\s+", " ", "too many spaces")
re.split(r"[,;]\s*", "a, b; c") # ['a', 'b', 'c']
re.compile(r"\d+").match("123abc")
# collections
from collections import Counter, defaultdict, OrderedDict, deque, namedtuple
# itertools
from itertools import chain, product, combinations, permutations, groupby, islice
list(chain([1, 2], [3, 4])) # [1, 2, 3, 4]
list(combinations("ABCD", 2))
list(permutations([1, 2, 3], 2))
# typing
from typing import Optional, Union, List, Dict, Tuple, Any, Callable
# Python 3.10+: use int | None instead of Optional[int]
# copy
import copy
shallow = copy.copy(obj)
deep = copy.deepcopy(obj)
# math
import math
math.pi # 3.14159...
math.sqrt(16) # 4.0
math.ceil(2.1) # 3
math.floor(2.9) # 2
math.log(100, 10) # 2.0
# random
import random
random.random() # float [0.0, 1.0)
random.randint(1, 6) # inclusive
random.choice(lst)
random.shuffle(lst) # in-place
random.sample(lst, k=3) # k unique items
# Use secrets for cryptographic randomness
import secrets
secrets.randbelow(100)
secrets.choice(lst)
Comprehensions quick reference
# List
[expr for x in iterable if condition]
# Dict
{k: v for k, v in items if condition}
# Set
{expr for x in iterable}
# Generator (lazy, no brackets)
(expr for x in iterable)
# Nested
matrix = [[1,2,3],[4,5,6],[7,8,9]]
flat = [cell for row in matrix for cell in row]
# Conditional expression inside
labels = ["even" if x % 2 == 0 else "odd" for x in range(5)]
6 common mistakes
1. Mutable default argument
# WRONG — lst is shared across all calls
def add(x, lst=[]):
lst.append(x)
return lst
# CORRECT
def add(x, lst=None):
if lst is None:
lst = []
lst.append(x)
return lst
2. Modifying a list while iterating
# WRONG
for item in lst:
if condition:
lst.remove(item)
# CORRECT — iterate a copy
for item in lst[:]:
if condition:
lst.remove(item)
# Or use a comprehension
lst = [item for item in lst if not condition]
3. Using == to compare with None
# WRONG
if x == None:
# CORRECT — None is a singleton
if x is None:
if x is not None:
4. Catching bare Exception and silently swallowing it
# WRONG
try:
risky()
except: # catches SystemExit, KeyboardInterrupt too
pass
# CORRECT
try:
risky()
except ValueError as e:
logger.error(f"Bad value: {e}")
raise
5. String concatenation in a loop (O(n²))
# WRONG — creates a new string each iteration
result = ""
for s in big_list:
result += s
# CORRECT
result = "".join(big_list)
6. Not using pathlib for file paths
# WRONG — breaks on Windows
path = "data/" + folder + "/" + filename
# CORRECT
from pathlib import Path
path = Path("data") / folder / filename
FAQ
Q: What's the difference between is and ==?
== tests value equality. is tests object identity (same object in memory). Always use == for value comparison. Use is only for None, True, and False.
Q: When should I use a tuple vs a list?
Use a tuple for fixed, heterogeneous data (coordinates, records, function return values). Use a list for homogeneous, ordered, mutable collections. Tuples are also hashable (can be dict keys / set members).
Q: What is *args vs **kwargs?
*args collects extra positional arguments into a tuple. **kwargs collects extra keyword arguments into a dict. You can use them together: def fn(*args, **kwargs).
Q: How do I copy a dict or list without aliasing?
# Shallow copy — nested objects are still shared
lst_copy = lst.copy() # or lst[:]
dict_copy = d.copy() # or dict(d)
# Deep copy — fully independent
import copy
deep = copy.deepcopy(obj)
Q: What is a generator and when should I use one?
A generator produces values lazily (on demand) instead of building a full list in memory. Use them when iterating over large datasets, infinite sequences, or pipelines where you only need one item at a time. Create with yield or a generator expression (x for x in ...).
Q: How do I check the Python version and installed packages?
python --version # Python 3.12.4
python -m pip list # installed packages
python -m pip show numpy # info on one package