Every formatting job you'll google, in one place. The pattern is always f"{value:format}" — value, colon, format spec.
name, price, big, ratio = "Ada", 49.9, 1234567, 0.8756
f"{name}" # Ada basic
f"{price:.2f}" # 49.90 2 decimals ← most googled
f"{big:,}" # 1,234,567 thousands separator
f"{ratio:.1%}" # 87.6% percentage
f"{price:>10.2f}" # " 49.90" right-align, width 10
f"{name:<10}|" # "Ada |" left-align (tables!)
f"{name:^10}" # " Ada " centered
f"{42:05d}" # 00042 zero-padded
f"{255:x}" f"{255:b}" # ff / 11111111 hex, binary
f"{2+3}" # 5 any expression works
f"{price=}" # price=49.9 debug print (3.8+) ← underrated
f"{{literal}}" # {literal} escaped braces
from datetime import datetime
now = datetime.now()
f"{now:%Y-%m-%d}" # 2026-07-22
f"{now:%H:%M}" # 14:30
f"{now:%b %d, %Y}" # Jul 22, 2026
f"{now:%A}" # Wednesday
width, prec = 12, 3
f"{price:{width}.{prec}f}" # " 49.900" — specs can be variables too
f"{d["key"]}" is a SyntaxError — the inner double quotes end the string. Use different quotes: f"{d['key']}". Python 3.12+ allows same-quote nesting, but if your code might run on older versions, mixing quote styles stays the safe habit.
%s formatting and .format() in old code — read them, don't write them. One exception: logging (logger.info("x=%s", x)) keeps %-style on purpose, so the string is only built if the log level is active.