diff -r 4b379a690ae2 pep-0008.txt --- a/pep-0008.txt Thu Jul 25 22:21:27 2013 +1000 +++ b/pep-0008.txt Sat Jul 27 16:38:17 2013 +1000 @@ -4,11 +4,12 @@ Last-Modified: $Date$ Author: Guido van Rossum , Barry Warsaw + Nick Coghlan Status: Active Type: Process Content-Type: text/x-rst Created: 05-Jul-2001 -Post-History: 05-Jul-2001 +Post-History: 05-Jul-2001, 27-Jul-2013 Introduction @@ -23,6 +24,10 @@ Guido's original Python Style Guide essay, with some additions from 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 ====================================================== @@ -41,7 +46,7 @@ judgment. Look at other examples and decide what looks best. And don't hesitate to ask! -Two good reasons to break a particular rule: +Some especially good reasons to ignore a particular guideline: 1. When applying the rule would make the code less readable, even for someone who is used to reading code that follows the rules. @@ -50,6 +55,13 @@ for historic reasons) -- although this is also an opportunity to clean up someone else's mess (in true XP style). +3. Because the code in question predates the introduction of the rule and + there is no other reason to be modifying that code (especially if + conforming to the updated style guide risks breaking backwards + compatibility) + +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 ============ @@ -132,9 +144,14 @@ Never mix tabs and spaces. The most popular way of indenting Python is with spaces only. The -second-most popular way is with tabs only. Code indented with a -mixture of tabs and spaces should be converted to using spaces -exclusively. When invoking the Python command line interpreter with +second-most popular way is with tabs only. In Python 3, these are the +only two permitted options (mixing tabs and spaces in the same file will +raise an error). + +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 tabs and spaces. When using ``-tt`` these warnings become errors. These options are highly recommended! @@ -147,13 +164,15 @@ Limit all lines to a maximum of 79 characters. -There are still many devices around that are limited to 80 character -lines; plus, limiting windows to 80 characters makes it possible to -have several windows side-by-side. The default wrapping on such -devices disrupts the visual structure of the code, making it more -difficult to understand. Therefore, please limit all lines to a -maximum of 79 characters. For flowing long blocks of text (docstrings -or comments), limiting the length to 72 characters is recommended. +Limiting the required editor window width to 80 characters makes it possible +to have several files open side-by-side, and works well when using code +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. Some web based tools may not +offer line wrapping at all. Therefore, please limit all lines to a maximum +of 79 characters. For flowing long blocks of text (docstrings or comments), +limiting the length to 72 characters is recommended. The preferred way of wrapping long lines is by using Python's implied line continuation inside parentheses, brackets and braces. Long lines @@ -218,11 +237,11 @@ Latin-1 encoding (a.k.a. ISO-8859-1). For Python 3.0 and beyond, UTF-8 is preferred over Latin-1, see PEP 3120. -Files using ASCII should not have a coding cookie. Latin-1 (or UTF-8) -should only be used when a comment or docstring needs to mention an -author name that requires Latin-1; otherwise, using ``\x``, ``\u`` or -``\U`` escapes is the preferred way to include non-ASCII data in -string literals. +Files using ASCII (in Python 2) or UTF-8 (in Python 3) should not have a +coding cookie. Latin-1 (or UTF-8) should only be used in Python 2 when a +comment or docstring needs to mention an author name that requires Latin-1; +otherwise, using ``\x``, ``\u`` or ``\U`` 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 standard library (see PEP 3131): All identifiers in the Python @@ -266,11 +285,27 @@ Put any relevant ``__all__`` specification after the imports. -- Relative imports for intra-package imports are highly discouraged. - Always use the absolute package path for all imports. Even now that - PEP 328 is fully implemented in Python 2.5, its style of explicit - relative imports is actively discouraged; absolute imports are more - portable and usually more readable. +- Absolute imports are recommended, as they are usually more readable and + tend to be better behaved (or at least give better error messages) if the + mport system is incorrectly configured (such as when a directory inside a + package ends up on ``sys.path``):: + + 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 okay to spell this:: @@ -285,6 +320,13 @@ and use "myclass.MyClass" and "foo.bar.yourclass.YourClass". +- Wildcard imports (``from 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). + Whitespace in Expressions and Statements ======================================== @@ -760,6 +802,36 @@ 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 =========================== @@ -769,10 +841,11 @@ For example, do not rely on CPython's efficient implementation of in-place string concatenation for statements in the form ``a += b`` - or ``a = a + b``. Those statements run more slowly in Jython. In - performance sensitive parts of the library, the ``''.join()`` form - should be used instead. This will ensure that concatenation occurs - in linear time across various implementations. + or ``a = a + b``. This optimisation is fragile even in CPython (it only + works for some types) and isn't present at all in implementations that + don't use refcounting. In performance sensitive parts of the 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 ``is`` or ``is not``, never the equality operators. @@ -799,29 +872,57 @@ operator. However, it is best to implement all six operations so 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 - feature has been removed in Python 2.6. + Yes:: - Modules or packages should define their own domain-specific base - exception class, which should be subclassed from the built-in - Exception class. Always include a class docstring. E.g.:: + def f(x): return 2*x - class MessageError(Exception): - """Base class for errors in the email package.""" + No:: + + f = lambda x: 2*x + + The first form means that the name of the resulting function object is + specifically 'f' instead of the generic ''. 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) + +- Use class-based exceptions (recent versions of Python require that all + exceptions inherit from BaseException). + + 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 - suffix "Error" to your exception classes, if the exception is an - error. Non-error exceptions need no special suffix. + suffix "Error" to your exception classes if the exception is an + 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'``. - The paren-using form is preferred because when the exception - arguments are long or include string formatting, you don't need to - use line continuation characters thanks to the containing - parentheses. The older form is not legal syntax in Python 3. + The latter form is not legal Python 3 syntax. + + The paren-using form also means that when the exception arguments are + 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 possible instead of using a bare ``except:`` clause. @@ -851,6 +952,20 @@ exception propagate upwards with ``raise``. ``try...finally`` 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 to the absolute minimum amount of code necessary. Again, this avoids masking bugs. @@ -907,9 +1022,6 @@ Yes: if foo.startswith('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 comparing types directly. :: @@ -918,11 +1030,15 @@ No: if type(obj) is type(1): 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:: 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 sequences are false. :: @@ -947,6 +1063,10 @@ annotation style. Instead, the annotations are left for users to discover and experiment with useful annotation styles. + It is highly recommended that third party experimants with annotations + use an associated decorator to indicate how the annotation should be + intepreted. + Early core developer attempts to use function annotations revealed inconsistent, ad-hoc annotation styles. For example: