One of Guido's key insights is that code is read much more often than it is written. - PEP8
There should be one—and preferably only one—obvious way to do it. - The Zen of Python
Any fool can write code that a computer can understand. Good programmers write code that humans can understand. - Martin Fowler
After Julian's two recent style posts on indentation and naming convention a nice follow-up is PEP8, the Style Guide for Python Code. Also a comment on Twitter caught my eye stating that even book authors do not always follow PEP8!
I think everybody writing code in Python should become familiar with PEP8 and use its guidelines rather sooner than later.
It leads to more readable code which saves brain cycles and better maintainable code (= fewer bug).
Also sharing a common coding style makes it easier to collaborate with others in the Python community.
Of course there can be exceptions to the rule, PEP8 states: "do not break backwards compatibility just to comply with this PEP!" - Raymond Hettinger did a great talk on this: Beyond PEP 8
Summary of the guidelines
A read that is aimed for '5 min' cannot have all, so I just summarize what I think is important, read the full spec for details:
Use 4 spaces per indentation level. Use spaces, not tabs. See our post for more on this, including recommended .vimrc settings. Overall watch your use of whitespace: this takes practice, but becomes habit/ automatic over time.
Limit all lines to a maximum of 79 characters. Usually I have a script.py and test_script.py open, vertically alligned (vi -O file1 file2), keeping lines short makes this very convenient.
Imports I) be as specific as possible with your imports:
# don't do: from time import * (unless needed, then use the __all__ mechanism to prevent exporting globals) # do: from time import time # or: import time # then prepends each method with module name: time.time()
Imports II) absolute imports are recommended:
from mypkg.sibling import example # over from .sibling import example
Imports III) split imports in stdlib - third party - application/library specific. For example our twitter bot followed this convention:
# stdlib import datetime import logging import time # pip installed import feedparser import tweepy # app modules from config import ... ...
Comments that contradict the code are worse than no comments, so keep them up2date. Use inline comments sparingly. Of course good code is mostly self-documenting.
"""Multi-line docstrings consist of a summary line just like a one-line docstring Followed by a blank line, followed by a more elaborate description. """
Non-public methods and instance variables start with a leading underscore: _helper_method(), although not enforced by the compiler, the reader knows this is an internal method, not to be called from outside of the class.
If you need to use a Python keyword append an underscore: str_ = 'bob'
You probably want to avoid single-char variables all together, but if you use them never use these easily confused chars: 'l' (lowercase letter el), 'O' (uppercase letter oh), or 'I' (uppercase letter eye).
Use CapWords for class names.
Use short, all-lowercase names for modules.
Use lowercase and underscores for method names.
Constants are all uppercase, in our Twitter bot example: CONSUMER_KEY, CONSUMER_SECRET, etc.
Programming Recommendations has some great tips: use ''.join(list) instead of string concatenation which is slow, use str.startswith/endswith instead of slicing (or more generically don't re-invent the wheel), boolean checks don't need == True/False, be consistent in return statements (even if returning None, use return None, not just return).
Interesting is the part on exceptions: two common mis-uses are putting too much in the try block, or catching exceptions that are too generic, so train yourself to use specific exceptions: 'except SomeError' instead of the catch-all 'except'.
Another interesting best practice is checking booleans, newcomers usually check False like 'if len(somelist) == 0', the Pythonic way is to just to use the fact that non-empty values are implicitly True, so in this case you could just do: 'if not somelist'.
Tools to check for compliant PEP8
You can use pep8
$ pip install pep8
Our digest.py seemed compliant but let's make some edits to see this checker in action. I changed spaces from 4 to 2 in a method, mis-aligned a multi-line statement, and removed a whitespace before '='. Of course pep8 complains:
$ pep8 digest.py digest.py:24:3: E111 indentation is not a multiple of four digest.py:25:3: E111 indentation is not a multiple of four digest.py:26:3: E111 indentation is not a multiple of four digest.py:50:18: E225 missing whitespace around operator digest.py:54:80: E501 line too long (83 > 79 characters)
Another tool is flake8 which is "a wrapper around these tools: PyFlakes, pycodestyle and Ned Batchelder’s McCabe script". It also has a nice integration in Vim: it runs the checks and presents them in a split window with line numbers, pretty convenient!
Btw I got this split window pressing ,f which I find easier on a Mac than F7, you can create a shortcut like this in your .vimrc:
autocmd FileType python map <buffer> ,f :call Flake8()<CR>
Another linter is pylint but I have not used that. What is your favorite linter?
Wrapping it up
Always follow the PEP 8 style guide when writing Python code.
Therefor keep a copy of PEP8 at hand and review it often to ingrain its recommendations. It makes code cleaner and collaboration easier.
Using a linter tool is the best way to remind/ train yourself. Just google for plugins / integration with your favorite editor.
Any feedback, questions or experiences, use the comments below.
Keep Calm and Code in Python!