Modern Python syntax — functions, comprehensions, async/await, dataclasses, FastAPI, Pydantic — with copy-paste examples
name = "Alice" # str
age = 30 # int
price = 19.99 # float
active = True # bool
nothing = None # NoneTypeprint(f"Hello {name}") # f-string (3.6+)
print("Score:", score) # multiple argstype(value) # returns type objectdef greet(name: str) -> None:# List — mutable, ordered
nums = [1, 2, 3]
nums.append(4)
nums[0] = 99# Tuple — immutable, ordered
point = (10, 20)
x, y = point # unpacking# Dict — key-value map
user = {"id": 1, "name": "Alice"}
user["email"] = "a@example.com"
user.get("phone", "N/A") # safe get# Set — unique, unordered
tags = {"python", "fastapi", "pydantic"}
tags.add("async")list and dict are mutable. tuple and frozenset are immutable. Use collections.defaultdict for auto-initializing dicts.False, None, 0, 0.0, "", [], {}, (), set()if mylist: # checks len()>0if mydict: # checks len()>0if x is None: # explicit None checkif not items: # empty check
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
else:
grade = "C"# Ternary
status = "active" if user.active else "inactive"for i in range(5): # 0..4for i in range(1, 6): # 1..5for i in range(0, 10, 2): # step 2
for item in items:
print(item)for i, item in enumerate(items):
print(i, item)
while running:
...
if stop: break
continue # skip to next
def greet(name):
return f"Hello {name}"def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b# *args, **kwargs
def log(msg, *args, **kwargs):
print(msg, args, kwargs)log("Error", 404, exc="timeout")
# → Error (404,) {'exc': 'timeout'}*args collects positional extras as tuple. **kwargs collects keyword extras as dict. Positional-only (before /) and keyword-only (after *) params available in 3.8+.square = lambda x: x * x
result = square(5) # 25# Used with map/filter/sorted
nums = [1, 2, 3]
doubled = list(map(lambda x: x*2, nums))# key functions
pairs = [(1, 'one'), (3, 'three'), (2, 'two')]
pairs.sort(key=lambda p: p[1]) # sort by stringdef. Python's lambda is limited to single expression (no statements).def greet(name="World"):
return f"Hello {name}"def f(pos, /, standard, *, kw_only): ...# pos: positional-only, kw_only: keyword-only
def make_multiplier(n):
def multiply(x):
return x * n
return multiply
double = make_multiplier(2)
squares = [x**2 for x in range(10)]# with condition
even_squares = [x**2 for x in range(10) if x % 2 == 0]# if-else inside
labels = ["even" if x%2==0 else "odd" for x in nums]for loop instead.square_map = {x: x**2 for x in range(5)}# {0:0, 1:1, 2:4, 3:9, 4:16}
unique_squares = {x**2 for x in [1, -2, 3, -2, 1]}# {1, 4, 9}
gen = (x**2 for x in range(1000000))
# values computed on demand
# File auto-close
with open("data.txt", "r") as f:
content = f.read() # file closes automatically# Multiple context managers
with open("in.txt") as fin, open("out.txt", "w") as fout:
fout.write(fin.read())with guarantees cleanup even on exception. Custom context managers implement __enter__ / __exit__ or use @contextmanager decorator from contextlib.from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
# auto __init__, __repr__, __eq__from dataclasses import dataclass, field
@dataclass
class User:
id: int
name: str
tags: list[str] = field(default_factory=list)@dataclass auto-generates __init__, __repr__, __eq__. field(default_factory=list) avoids mutable default pitfall. Python 3.10+ supports list[str] syntax for type hints.import functools
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.time()-start:.2f}s")
return result
return wrapper
@timer
def slow_func():
time.sleep(1)
@functools.wraps(func) to preserve __name__, __doc__ of decorated function. Decorators are just callables that wrap functions.import asyncio
async def fetch_data():
await asyncio.sleep(1) # non-blocking sleep
return {"result": 42}
async def main():
data = await fetch_data()
print(data)
asyncio.run(main())async def defines coroutine function. await pauses until coroutine completes. Run with asyncio.run() (main) or await inside another async function. Use FastAPI or Starlette for web apps.results = await asyncio.gather(fetch(1), fetch(2), fetch(3))# all run concurrently, return list of results
task = asyncio.create_task(background_job())
# don't await immediately
gather() waits for all. create_task() schedules and returns Task immediately. Cancel tasks on shutdown if needed.try:
result = 10 / divisor
except ZeroDivisionError:
print("Cannot divide by zero")
except Exception as e:
print(f"Unexpected: {e}")
else:
print("Success!", result)
finally:
cleanup() # always runselse runs if no exception. finally runs always (cleanup). Catch specific exceptions first, broad ones last.raise ValueError("Invalid input")
raise TypeError("Expected str")
class AppError(Exception):
pass
raise AppError("Something went wrong")
# Assign inside expression
if (n := len(items)) > 0:
print(f"List has {n} items")# While reading lines from file
while (line := f.readline()):
process(line):= assigns and returns value. Reduces duplicate calls. Use sparingly — readability matters. Not for complex expressions.match command:
case ["goto", x, y]:
print(f"Go to {x},{y}")
case ["quit"]:
print("Goodbye")
case _:
print("Unknown")match status:
case 200:
print("OK")
case 404:
print("Not found")
case int(code) if code >= 500:
print("Server error")match is like switch but powerful — matches on structure, type, and value. Guard clauses (if after case) add conditions.def greet(name, /, greeting="Hello", *, excited=False):
msg = f"{greeting} {name}"
if excited: msg += "!"
return msg
greet("Bob") # OK
greet(name="Bob") # ❌ name is positional-only
greet("Bob", "Hi", excited=True) # OK/ marks preceding args positional-only. * marks following args keyword-only. Signals API intent and prevents accidental misuse.The Python Cheat Sheet covers essential Python 3.8+ syntax and idioms. From basics like variables and collections, through functions, comprehensions, and async/await, to modern features like dataclasses and structural pattern matching. Each snippet is copy-ready and includes brief explanations.
"There should be one — and preferably only one — obvious way to do it." — The Zen of Python
This cheat sheet favors idiomatic Python: list comprehensions over map/filter, f-strings over format(), with for resource cleanup, and explicit is better than implicit.
Use list comprehensions when you're building a new list from an iterable with transformation and optional filtering. Use a for loop when you need side effects (printing, mutating external vars, complex multi-step logic that doesn't fit in one expression). List comps are faster and more readable for simple transformations.
async and threading?async/await is cooperative concurrency — tasks explicitly yield control at await points. It's single-threaded and ideal for I/O-bound work (API calls, file/DB ops). Threading is preemptive OS-managed concurrency — threads run truly parallel but share memory, requiring locks for thread-safety. Use async for many simultaneous I/O operations; use threading (or multiprocessing) for CPU-bound work.
Use @dataclass for simple, internal data containers with no validation — it's built-in and zero-dependency. Use Pydantic when you need runtime validation, parsing, JSON (de)serialization, ORM-like features, or complex type coercion. Pydantic v2 is much faster and has better error messages. For public APIs and config, Pydantic. For private simple structs, dataclasses.
Yes, completely free with no sign-up required.
uuid.uuid4())