Readable Code: Style, Formatters and Linters
About 18 minutes
Why this matters
Code is read far more often than it is written, mostly by you, months later. Consistent style makes code easy to read and bugs easy to spot. Python has a shared style guide (PEP 8), and tools that apply it for you, so you do not have to argue about it.
The idea
The conventions you will see in almost every Python project:
| Thing | Style | Example |
|---|---|---|
| variables, functions | snake_case |
total_price, read_number |
| classes | CapWords |
ShoppingCart |
| constants | UPPER_CASE |
MAX_ITEMS |
| indentation | 4 spaces, no tabs | |
| line length | about 79 to 88 characters | |
| imports | one per line, at the top, none unused | import os |
| docstring | on every public function | """Add two numbers.""" |
A few habits prevent real bugs, not just ugliness:
- Compare with
Noneusingis None, not== None. - Never use a mutable default (
def f(items=[])): the same list is shared by every call. Useitems=None. - Catch specific errors (
except ValueError:), never a bareexcept:that also hides typos andCtrl+C. - Return a condition directly:
return a > b, notif a > b: return True else: return False.
Two kinds of tool help:
- A formatter rewrites your code layout automatically:
ruff format file.py(orblack). - A linter reports problems without changing meaning:
ruff check file.pyfinds unused imports, bad names, risky patterns.ruff check --fixrepairs many of them.
Install with pip install ruff on your own computer. The checks in this lesson use a small checker that looks for the same problems, so you can practise here in the browser.
Try it
Look at the starter code and spot as many problems as you can before reading on. Then try the table above as a checklist.
Your turn
The starter contains messy but working code. Clean it up without changing what it does:
- Rename
Calc_Totaltocalculate_total,IsValidEmailtois_valid_emailandreadNumbertoread_number, andmaxItemstoMAX_ITEMS. - Remove the unused imports.
- Fix the mutable default, the
== Noneand the bareexcept. - Add a docstring to every function.
- Keep lines to 79 characters, with no tabs and no trailing spaces.
Recap
- Follow PEP 8:
snake_casefunctions,CapWordsclasses,UPPER_CASEconstants. - Avoid mutable default arguments, bare
exceptand== None. - A formatter fixes layout; a linter finds likely mistakes.
ruffdoes both. - Clean code is easier to test and to change.
Common mistakes
- Renaming a function but not its callers.
- Fixing style and changing behaviour at the same time. Run your tests after every cleanup.
- Fighting the formatter. Agree on one tool and let it decide.