PEP 8 modernisation

Thanks to Guido van Rossum, Barry Warsaw, Raymond Hettinger,
Terry Reedy, Thomas Wouters and others for the constructive
feedback :)
This commit is contained in:
Nick Coghlan 2013-08-01 22:25:37 +10:00
parent 2ea8f1200a
commit 7dba60ceea
1 changed files with 198 additions and 59 deletions

View File

@ -3,12 +3,13 @@ Title: Style Guide for Python Code
Version: $Revision$ Version: $Revision$
Last-Modified: $Date$ Last-Modified: $Date$
Author: Guido van Rossum <guido@python.org>, Author: Guido van Rossum <guido@python.org>,
Barry Warsaw <barry@python.org> Barry Warsaw <barry@python.org>,
Nick Coghlan <ncoghlan@gmail.com>
Status: Active Status: Active
Type: Process Type: Process
Content-Type: text/x-rst Content-Type: text/x-rst
Created: 05-Jul-2001 Created: 05-Jul-2001
Post-History: 05-Jul-2001 Post-History: 05-Jul-2001, 01-Aug-2013
Introduction Introduction
@ -23,6 +24,10 @@ This document and PEP 257 (Docstring Conventions) were adapted from
Guido's original Python Style Guide essay, with some additions from Guido's original Python Style Guide essay, with some additions from
Barry's style guide [2]_. Barry's style guide [2]_.
This style guide evolves over time as additional conventions are
identified and past conventions are rendered obsolete by changes in
the language itself.
A Foolish Consistency is the Hobgoblin of Little Minds A Foolish Consistency is the Hobgoblin of Little Minds
====================================================== ======================================================
@ -41,15 +46,24 @@ style guide just doesn't apply. When in doubt, use your best
judgment. Look at other examples and decide what looks best. And judgment. Look at other examples and decide what looks best. And
don't hesitate to ask! don't hesitate to ask!
Two good reasons to break a particular rule: In particular: do not break backwards compatibility just to comply with
this PEP!
1. When applying the rule would make the code less readable, even for Some other good reasons to ignore a particular guideline:
someone who is used to reading code that follows the rules.
1. When applying the guideline would make the code less readable, even
for someone who is used to reading code that follows this PEP.
2. To be consistent with surrounding code that also breaks it (maybe 2. To be consistent with surrounding code that also breaks it (maybe
for historic reasons) -- although this is also an opportunity to for historic reasons) -- although this is also an opportunity to
clean up someone else's mess (in true XP style). clean up someone else's mess (in true XP style).
3. Because the code in question predates the introduction of the
guideline and there is no other reason to be modifying that code.
4. When the code needs to remain compatible with older versions of
Python that don't support the feature recommended by the style guide.
Code lay-out Code lay-out
============ ============
@ -59,9 +73,6 @@ Indentation
Use 4 spaces per indentation level. Use 4 spaces per indentation level.
For really old code that you don't want to mess up, you can continue
to use 8-space tabs.
Continuation lines should align wrapped elements either vertically Continuation lines should align wrapped elements either vertically
using Python's implicit line joining inside parentheses, brackets and using Python's implicit line joining inside parentheses, brackets and
braces, or using a hanging indent. When using a hanging indent the braces, or using a hanging indent. When using a hanging indent the
@ -129,31 +140,41 @@ starts the multi-line construct, as in::
Tabs or Spaces? Tabs or Spaces?
--------------- ---------------
Never mix tabs and spaces. Spaces are the preferred indentation method.
The most popular way of indenting Python is with spaces only. The Tabs should be used solely to remain consistent with code that is
second-most popular way is with tabs only. Code indented with a already indented with tabs.
mixture of tabs and spaces should be converted to using spaces
exclusively. When invoking the Python command line interpreter with Python 3 disallows mixing the use of tabs and spaces for indentation.
Python 2 code indented with a mixture of tabs and spaces should be
converted to using spaces exclusively.
When invoking the Python 2 command line interpreter with
the ``-t`` option, it issues warnings about code that illegally mixes the ``-t`` option, it issues warnings about code that illegally mixes
tabs and spaces. When using ``-tt`` these warnings become errors. tabs and spaces. When using ``-tt`` these warnings become errors.
These options are highly recommended! These options are highly recommended!
For new projects, spaces-only are strongly recommended over tabs.
Most editors have features that make this easy to do.
Maximum Line Length Maximum Line Length
------------------- -------------------
Limit all lines to a maximum of 79 characters. Aim to limit all lines to a maximum of 79 characters, but up to 99
characters is acceptable when it improves readability.
There are still many devices around that are limited to 80 character For flowing long blocks of text with fewer structural restrictions
lines; plus, limiting windows to 80 characters makes it possible to (docstrings or comments), limiting the line length to 72 characters
have several windows side-by-side. The default wrapping on such is recommended.
devices disrupts the visual structure of the code, making it more
difficult to understand. Therefore, please limit all lines to a Limiting the required editor window width makes it possible to have
maximum of 79 characters. For flowing long blocks of text (docstrings several files open side-by-side, and works well when using code
or comments), limiting the length to 72 characters is recommended. review tools that present the two versions in adjacent columns.
The default wrapping in most tools disrupts the visual structure of the
code, making it more difficult to understand. The limits are chosen to
avoid wrapping in editors with the window width set to 80 (or 100), even
if the tool places a marker glyph in the final column when wrapping
lines. Some web based tools may not offer dynamic line wrapping at all.
The preferred way of wrapping long lines is by using Python's implied The preferred way of wrapping long lines is by using Python's implied
line continuation inside parentheses, brackets and braces. Long lines line continuation inside parentheses, brackets and braces. Long lines
@ -214,15 +235,17 @@ control-L as a form feed and will show another glyph in its place.
Encodings (PEP 263) Encodings (PEP 263)
------------------- -------------------
Code in the core Python distribution should always use the ASCII or Code in the core Python distribution should always use UTF-8 (or ASCII
Latin-1 encoding (a.k.a. ISO-8859-1). For Python 3.0 and beyond, in Python 2).
UTF-8 is preferred over Latin-1, see PEP 3120.
Files using ASCII should not have a coding cookie. Latin-1 (or UTF-8) Files using ASCII (in Python 2) or UTF-8 (in Python 3) should not have a
should only be used when a comment or docstring needs to mention an coding cookie.
author name that requires Latin-1; otherwise, using ``\x``, ``\u`` or
``\U`` escapes is the preferred way to include non-ASCII data in In the standard library, non-default encodings should be used only for
string literals. test purposes or when a comment or docstring needs to mention an author
name that that contains non-ASCII characters; otherwise, using ``\x``,
``\u``, ``\U``, or ``\N`` escapes is the preferred way to include
non-ASCII data in string literals.
For Python 3.0 and beyond, the following policy is prescribed for the For Python 3.0 and beyond, the following policy is prescribed for the
standard library (see PEP 3131): All identifiers in the Python standard library (see PEP 3131): All identifiers in the Python
@ -266,11 +289,27 @@ Imports
Put any relevant ``__all__`` specification after the imports. Put any relevant ``__all__`` specification after the imports.
- Relative imports for intra-package imports are highly discouraged. - Absolute imports are recommended, as they are usually more readable
Always use the absolute package path for all imports. Even now that and tend to be better behaved (or at least give better error
PEP 328 is fully implemented in Python 2.5, its style of explicit messages) if the import system is incorrectly configured (such as
relative imports is actively discouraged; absolute imports are more when a directory inside a package ends up on ``sys.path``)::
portable and usually more readable.
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
However, explicit relative imports are an acceptable alternative to
absolute imports, especially when dealing with complex package layouts
where using absolute imports would be unecessarily verbose::
from . import sibling
from .sibling import example
Standard library code should avoid complex package layouts and always
use absolute imports.
Implicit relative imports should *never* be used and have been removed
in Python 3.
- When importing a class from a class-containing module, it's usually - When importing a class from a class-containing module, it's usually
okay to spell this:: okay to spell this::
@ -285,6 +324,18 @@ Imports
and use "myclass.MyClass" and "foo.bar.yourclass.YourClass". and use "myclass.MyClass" and "foo.bar.yourclass.YourClass".
- Wildcard imports (``from <module> import *``) should be avoided, as
they make it unclear which names are present in the namespace,
confusing both readers and many automated tools. There is one
defensible use case for a wildcard import, which is to republish an
internal interface as part of a public API (for example, overwriting
a pure Python implementation of an interface with the definitions
from an optional accelerator module and exactly which definitions
will be overwritten isn't known in advance).
When republishing names this way, the guidelines below regarding
public and internal interfaces still apply.
Whitespace in Expressions and Statements Whitespace in Expressions and Statements
======================================== ========================================
@ -760,6 +811,36 @@ With this in mind, here are the Pythonic guidelines:
advanced callers. advanced callers.
Public and internal interfaces
------------------------------
Any backwards compatibility guarantees apply only to public interfaces.
Accordingly, it is important that users be able to clearly distinguish
between public and internal interfaces.
Documented interfaces are considered public, unless the documentation
explicitly declares them to be provisional or internal interfaces exempt
from the usual backwards compatibility guarantees. All undocumented
interfaces should be assumed to be internal.
To better support introspection, modules should explicitly declare the
names in their public API using the ``__all__`` attribute. Setting
``__all__`` to an empty list indicates that the module has no public API.
Even with ``__all__`` set appropriately, internal interfaces (packages,
modules, classes, functions, attributes or other names) should still be
prefixed with a single leading underscore.
An interface is also considered internal if any containing namespace
(package, module or class) is considered internal.
Imported names should always be considered an implementation detail.
Other modules must not rely on indirect access to such imported names
unless they are an explicitly documented part of the containing module's
API, such as ``os.path`` or a package's ``__init__`` module that exposes
functionality from submodules.
Programming Recommendations Programming Recommendations
=========================== ===========================
@ -769,10 +850,12 @@ Programming Recommendations
For example, do not rely on CPython's efficient implementation of For example, do not rely on CPython's efficient implementation of
in-place string concatenation for statements in the form ``a += b`` in-place string concatenation for statements in the form ``a += b``
or ``a = a + b``. Those statements run more slowly in Jython. In or ``a = a + b``. This optimization is fragile even in CPython (it
performance sensitive parts of the library, the ``''.join()`` form only works for some types) and isn't present at all in implementations
should be used instead. This will ensure that concatenation occurs that don't use refcounting. In performance sensitive parts of the
in linear time across various implementations. library, the ``''.join()`` form should be used instead. This will
ensure that concatenation occurs in linear time across various
implementations.
- Comparisons to singletons like None should always be done with - Comparisons to singletons like None should always be done with
``is`` or ``is not``, never the equality operators. ``is`` or ``is not``, never the equality operators.
@ -799,29 +882,59 @@ Programming Recommendations
operator. However, it is best to implement all six operations so operator. However, it is best to implement all six operations so
that confusion doesn't arise in other contexts. that confusion doesn't arise in other contexts.
- Use class-based exceptions. - Always use a def statement instead of assigning a lambda expression
to a name.
String exceptions in new code are forbidden, and this language Yes::
feature has been removed in Python 2.6.
Modules or packages should define their own domain-specific base def f(x): return 2*x
exception class, which should be subclassed from the built-in
Exception class. Always include a class docstring. E.g.::
class MessageError(Exception): No::
"""Base class for errors in the email package."""
f = lambda x: 2*x
The first form means that the name of the resulting function object is
specifically 'f' instead of the generic '<lambda>'. This is more
useful for tracebacks and string representations in general. The use
of the assignment statement eliminates the sole benefit a lambda
expression can offer over an explicit def statement (i.e. that it can
be embedded inside a larger expression)
- Derive exceptions from ``Exception`` rather than ``BaseException``.
Direct inheritance from ``BaseException`` is reserved for exceptions
where catching them is almost always the wrong thing to do.
Design exception hierarchies based on the distinctions that code
*catching* the exceptions is likely to need, rather than the locations
where the exceptions are raised. Aim to answer the question
"What went wrong?" programmatically, rather than only stating that
"A problem occurred" (see PEP 3151 for an example of this lesson being
learned for the builtin exception hierarchy)
Class naming conventions apply here, although you should add the Class naming conventions apply here, although you should add the
suffix "Error" to your exception classes, if the exception is an suffix "Error" to your exception classes if the exception is an
error. Non-error exceptions need no special suffix. error. Non-error exceptions that are used for non-local flow control
or other forms of signalling need no special suffix.
- When raising an exception, use ``raise ValueError('message')`` - Use exception chaining appropriately. In Python 3, "raise X from Y"
should be used to indicate explicit replacement without losing the
original traceback.
When deliberately replacing an inner exception (using "raise X" in
Python 2 or "raise X from None" in Python 3.3+), ensure that relevant
details are transferred to the new exception (such as preserving the
attribute name when converting KeyError to AttributeError, or
embedding the text of the original exception in the new exception
message).
- When raising an exception in Python 2, use ``raise ValueError('message')``
instead of the older form ``raise ValueError, 'message'``. instead of the older form ``raise ValueError, 'message'``.
The paren-using form is preferred because when the exception The latter form is not legal Python 3 syntax.
arguments are long or include string formatting, you don't need to
use line continuation characters thanks to the containing The paren-using form also means that when the exception arguments are
parentheses. The older form is not legal syntax in Python 3. long or include string formatting, you don't need to use line
continuation characters thanks to the containing parentheses.
- When catching exceptions, mention specific exceptions whenever - When catching exceptions, mention specific exceptions whenever
possible instead of using a bare ``except:`` clause. possible instead of using a bare ``except:`` clause.
@ -851,6 +964,21 @@ Programming Recommendations
exception propagate upwards with ``raise``. ``try...finally`` exception propagate upwards with ``raise``. ``try...finally``
can be a better way to handle this case. can be a better way to handle this case.
- When binding caught exceptions to a name, prefer the explicit name
binding syntax added in Python 2.6::
try:
process_data()
except Exception as exc:
raise DataProcessingFailedError(str(exc))
This is the only syntax supported in Python 3, and avoids the
ambiguity problems associated with the older comma-based syntax.
- When catching operating system errors, prefer the explicit exception
hierarchy introduced in Python 3.3 over introspection of ``errno``
values.
- Additionally, for all try/except clauses, limit the ``try`` clause - Additionally, for all try/except clauses, limit the ``try`` clause
to the absolute minimum amount of code necessary. Again, this to the absolute minimum amount of code necessary. Again, this
avoids masking bugs. avoids masking bugs.
@ -873,6 +1001,10 @@ Programming Recommendations
# Will also catch KeyError raised by handle_value() # Will also catch KeyError raised by handle_value()
return key_not_found(key) return key_not_found(key)
- When a resource is local to a particular section of code, use a
``with`` statement to ensure it is cleaned up promptly and reliably
after use. A try/finally statement is also acceptable.
- Context managers should be invoked through separate functions or methods - Context managers should be invoked through separate functions or methods
whenever they do something other than acquire and release resources. whenever they do something other than acquire and release resources.
For example: For example:
@ -907,9 +1039,6 @@ Programming Recommendations
Yes: if foo.startswith('bar'): Yes: if foo.startswith('bar'):
No: if foo[:3] == 'bar': No: if foo[:3] == 'bar':
The exception is if your code must work with Python 1.5.2 (but let's
hope not!).
- Object type comparisons should always use isinstance() instead of - Object type comparisons should always use isinstance() instead of
comparing types directly. :: comparing types directly. ::
@ -918,11 +1047,15 @@ Programming Recommendations
No: if type(obj) is type(1): No: if type(obj) is type(1):
When checking if an object is a string, keep in mind that it might When checking if an object is a string, keep in mind that it might
be a unicode string too! In Python 2.3, str and unicode have a be a unicode string too! In Python 2, str and unicode have a
common base class, basestring, so you can do:: common base class, basestring, so you can do::
if isinstance(obj, basestring): if isinstance(obj, basestring):
Note that in Python 3, ``unicode`` and ``basestring`` no longer exist
(there is only ``str``) and a bytes object is no longer a kind of
string (it is a sequence of integers instead)
- For sequences, (strings, lists, tuples), use the fact that empty - For sequences, (strings, lists, tuples), use the fact that empty
sequences are false. :: sequences are false. ::
@ -947,6 +1080,10 @@ Programming Recommendations
annotation style. Instead, the annotations are left for users to annotation style. Instead, the annotations are left for users to
discover and experiment with useful annotation styles. discover and experiment with useful annotation styles.
It is recommended that third party experimants with annotations use an
associated decorator to indicate how the annotation should be
interpreted.
Early core developer attempts to use function annotations revealed Early core developer attempts to use function annotations revealed
inconsistent, ad-hoc annotation styles. For example: inconsistent, ad-hoc annotation styles. For example:
@ -1004,6 +1141,8 @@ References
.. [3] http://www.wikipedia.com/wiki/CamelCase .. [3] http://www.wikipedia.com/wiki/CamelCase
.. [4] PEP 8 modernisation, July 2013
http://bugs.python.org/issue18472
Copyright Copyright
========= =========