1. Code should be written in a way that does not disadvantage other implementations of Python (PyPy, Jython, IronPython, Pyrex, Psyco, and such).
a. 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.
b. 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.
2. Comparisons to singletons like None should always be done with 'is' or 'is not', never the equality operators.
a. Beware of writing "if x" when you really mean "if x is not None" -- e.g. when testing whether a variable or argument that defaults to None was set to some other value. The other value might have a type (such as a container) that could be false in a boolean context!
3. When implementing ordering operations with rich comparisons, it is best to implement all six operations (__eq__, __ne__, __lt__, __le__, __gt__, __ge__) rather than relying on other code to only exercise a particular comparison.
a. To minimize the effort involved, the functools.total_ordering() decorator provides a tool to generate missing comparison methods.
b. PEP 207 indicates that reflexivity rules *are* assumed by Python. Thus, the interpreter may swap y > x with x < y, y >= x with x <= y, and may swap the arguments of x == y and x != y. The sort() and min() operations are guaranteed to use the < operator and the max() function uses the > operator. However, it is best to implement all six operations so that confusion doesn't arise in other contexts.
4. Use class-based exceptions.
a. String exceptions in new code are forbidden, because this language feature is being removed in Python 2.6.
b. 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.:
class MessageError(Exception):
"""Base class for errors in the email package."""
c. 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.
5. When raising an exception, use "raise ValueError('message')" instead of the older form "raise ValueError, 'message'".
a. 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 will be removed in Python 3000.
6. When catching exceptions, mention specific exceptions whenever possible instead of using a bare 'except:' clause.
import platform_specific_module
except ImportError:
platform_specific_module = None
a. A bare 'except:' clause will catch SystemExit and KeyboardInterrupt exceptions, making it harder to interrupt a program with Control-C, and can disguise other problems. If you want to catch all exceptions that signal program errors, use 'except Exception:'.
b. A good rule of thumb is to limit use of bare 'except' clauses to two cases:
(1) If the exception handler will be printing out or logging the traceback; at least the user will be aware that an error has occurred.
(2) If the code needs to do some cleanup work, but then lets the exception propagate upwards with 'raise'. 'try...finally' is a better way to handle this case.
7. For all try/except clauses, limit the 'try' clause to the absolute minimum amount of code necessary. Again, this avoids masking bugs.
Yes: try:
value = collection[key]
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
No:
try:
# Too broad!
return handle_value(collection[key])
except KeyError:
# Will also catch KeyError raised by handle_value()
return key_not_found(key)
8. Use string methods instead of the string module.
a. String methods are always much faster and share the same API with unicode strings.
b. Override this rule if backward compatibility with Pythons older than 2.0 is required.
9. Use ''.startswith() and ''.endswith() instead of string slicing to check for prefixes or suffixes.
a. startswith() and endswith() are cleaner and less error prone.
Yes: if foo.startswith('bar'):
No: if foo[:3] == 'bar':
No: if foo[:3] == 'bar':
10. Object type comparisons should always use isinstance() instead of comparing types directly.
Yes: if isinstance(obj, int):
No: if type(obj) is type(1):
a. 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 common base class, basestring, so you can do:
if isinstance(obj, basestring):
11. For sequences, (strings, lists, tuples), use the fact that empty sequences are false.
if not seq:
if seq:
No:
if len(seq):
if not len(seq):
12. Don't write string literals that rely on significant trailing whitespace. Such trailing whitespace is visually indistinguishable and some editors (or more recently, reindent.py) will trim them.
13. Don't compare boolean values to True or False using ==
if greeting:
No:
if greeting == True:
Worse:
if greeting is True: