Python supports old `%` formatting, `str.format`, and f-strings, with f-strings usually being the clearest modern default.
- f-strings embed expressions directly
- format works well for reusable templates
- % formatting still appears in older code
Python testing usually combines clear assertions with a framework like `unittest` or `pytest`, plus fixtures and mocking where isolation matters.
- pytest emphasizes readability
- Fixtures manage reusable setup
- Mocking isolates dependencies but should be used carefully
The `if __name__ == "__main__"` guard separates script execution from import behavior, and package imports can be relative or absolute depending on context.
- `__name__` changes when imported
- Absolute imports are usually clearer
- Relative imports are useful inside packages
Threads are useful for I/O-bound concurrency, multiprocessing is better for CPU-bound parallel work in CPython, and `asyncio` organizes cooperative I/O with coroutines and `async`/`await`.
- GIL limits parallel bytecode execution in threads
- Asyncio is concurrency, not magic parallelism
- Choose the model based on the workload
Python treats certain values as false in conditionals, including `False`, `None`, zero values, and empty containers.
- Empty collections are falsy
- Most objects are truthy by default
- Truthiness powers concise condition checks
Tuples support packing multiple values together and unpacking them cleanly into separate names.
- Commas create tuples
- A singleton tuple needs a trailing comma
- Unpacking improves readability
Type hints document intent, improve tooling, and can express unions, optional values, generics, literal constraints, protocols, and escape hatches like `Any`.
- Hints help humans and tools
- `Protocol` supports structural typing
- Mypy and Pyright are common static type checkers
Virtual environments isolate dependencies per project, `pip` installs packages, and requirements files record what the project needs.
- Isolation avoids dependency conflicts
- `venv` is the built-in environment tool
- Pinned requirements improve repeatability
Context managers set up and clean up resources automatically, usually through the `with` statement.
- Uses with statement
- Handles cleanup even on errors
- Common for files and locks
Dataclasses reduce boilerplate for data-carrying classes by generating methods like `__init__` and `__repr__`.
- Great for structured data
- Supports defaults and type hints
- Not the same as full validation models
A decorator wraps another callable to add behavior without changing the original function body.
- Starts with a callable
- Usually returns a wrapper
- Common for logging, auth, caching
A generator yields values lazily so you can stream work instead of building the whole collection at once.
- Uses yield
- Keeps state between iterations
- Good for large data