| #summary Style guide for Python code contributed to Melange |
| #labels Contents-Draft,Phase-Guidelines,Importance-Featured,Featured |
| |
| The [SoCOverview SoC framework], and |
| [MelangeIntro Melange web applications] built upon it, are implemented in |
| Python (it is one of the programming language besides Java and Go which are currently supported by |
| [http://code.google.com/appengine/ Google App Engine]). This style guide is a |
| list of dos and don'ts for Python contributions to the Melange project. |
| |
| The rules below are not guidelines or recommendations, but strict rules. You |
| may not disregard the rules we list below except as approved on a need-to-use |
| basis. But note also the advice on [PythonStyleGuide#Conclusion consistency] |
| at the end of the guide. |
| |
| If you have questions about these guidelines, you can send mail to the |
| [MailingListsGuidelines#Developer_list developer mailing list]. |
| Please put *Python style:* in the subject line to make it easier to locate |
| these discussions in the mailing list archives. |
| |
| Since this style guide is documented in the Melange wiki, it can be changed via |
| the existing [DocumentationReviews documentation review process]. However, |
| changes to the style guide should not be made lightly, since |
| [PythonStyleGuide#Conclusion consistency] is one of the key goals |
| of this style guide, and old code will not necessarily be updated for new |
| style guide changes. |
| |
| = Summary = |
| |
| == Python Language Rules == |
| |
| # [PythonStyleGuide#pychecker pychecker]: _Recommended_ |
| # [PythonStyleGuide#Imports Imports]: _Import only modules and only by name *(no wildcard imports)*_ |
| # [PythonStyleGuide#Exceptions Exceptions]: _Yes_ |
| # [PythonStyleGuide#Global_variables Global variables]: _Use sparingly_ |
| # [PythonStyleGuide#Nested_Local_Inner_Classes_and_Functions Nested/Local/Inner Classes and Functions]: _Yes_ |
| # [PythonStyleGuide#List_Comprehensions List Comprehensions]: _Yes, *if simple*_ |
| # [PythonStyleGuide#Default_Iterators_and_Operators Default Iterators and Operators]: _Yes_ |
| # [PythonStyleGuide#Generators Generators]: _Yes_ |
| # [PythonStyleGuide#Using_apply_filter_map_reduce Using apply, filter, map, reduce]: _Yes, *for one-liners*_ |
| # [PythonStyleGuide#Lambda_functions Lambda functions]: _Yes, *for one-liners*_ |
| # [PythonStyleGuide#Default_Argument_Values Default Argument Values]: _Yes_ |
| # [PythonStyleGuide#Properties Properties]: _Yes_ |
| # [PythonStyleGuide#True_False_evaluations True/False evaluations]: _Yes_ |
| # [PythonStyleGuide#Boolean_built_in_type Boolean built-in type]: _Yes_ |
| # [PythonStyleGuide#String_Methods String Methods]: _Yes_ |
| # [PythonStyleGuide#Lexical_Scoping Lexical Scoping]: _Yes_ |
| # [PythonStyleGuide#Function_and_Method_Decorators Function and Method Decorators]: _Yes, *in moderation*_ |
| # [PythonStyleGuide#Threading Threading]: _*do not use* (not available in [http://code.google.com/appengine/kb/general.html#libraries Google App Engine])_ |
| # [PythonStyleGuide#Power_features Power features]: _*No*_ |
| |
| == Python Style Rules == |
| |
| Programs are much easier to maintain when all files have a consistent |
| style. Here is the canonical Melange Python style. |
| |
| # [PythonStyleGuide#Semicolons Semicolons]: _*Avoid*_ |
| # [PythonStyleGuide#Line_length Line length]: _*80* columns maximum_ |
| # [PythonStyleGuide#Parentheses Parentheses]: _*Use sparingly*_ |
| # [PythonStyleGuide#Indentation Indentation]: _*2* spaces (*no tabs*),_ *differs from [http://www.python.org/dev/peps/pep-0008/ PEP8]* |
| # [PythonStyleGuide#Blank_lines Blank lines]: _*2* for functions and classes, *1* for methods_ |
| # [PythonStyleGuide#Whitespace Whitespace]: _Sparingly within a line_ |
| # [PythonStyleGuide#Python_Interpreter Python Interpreter]: _the one supported by_ [http://code.google.com/appengine/docs/python/purepython.html Google App Engine]: `#!/usr/bin/python2.5` |
| # [PythonStyleGuide#Comments Comments]: _`__doc__` strings, block, inline_ |
| * [PythonStyleGuide#Doc_strings `__doc__` Strings] |
| * [PythonStyleGuide#Modules Modules] |
| * [PythonStyleGuide#Functions_and_Methods Functions and Methods] |
| * [PythonStyleGuide#Classes Classes] |
| * [PythonStyleGuide#Block_and_Inline_Comments Block and Inline Comments] |
| # [PythonStyleGuide#Classes Classes]: _Inherit from object_ |
| # [PythonStyleGuide#Strings Strings]: _Avoid repeated use of `+` and `+=`_ |
| # [PythonStyleGuide#TODO_style TODO style]: `TODO(username):` _use a consistent style_ |
| # [PythonStyleGuide#Imports_grouping_and_order Imports grouping, order and sorting]: _One per line, grouped and ordered by packages, sorted alphabetically_ |
| # [PythonStyleGuide#Statements Statements]: _One per line, avoid [PythonStyleGuide#Semicolons Semicolons]_ |
| # [PythonStyleGuide#Access_control Access control]: _`foo` if lightweight, `GetFoo()` and `SetFoo()` otherwise_ |
| # [PythonStyleGuide#Naming Naming]: _`foo_bar.py` not `foo-bar.py`,_ *some differ from [http://www.python.org/dev/peps/pep-0008/ PEP8]* |
| # [PythonStyleGuide#Main Main]: `if __name__ == '__main__':` |
| # [PythonStyleGuide#Conclusion Conclusion]: _Look at what's around you!_ |
| |
| = Python Language Rules = |
| |
| == pychecker == |
| |
| *What it is:* `pychecker` is a tool for finding bugs in Python source code. |
| It finds problems that are typically caught by a compiler for less dynamic |
| languages like C and C++. It is similar to lint. Because of the dynamic |
| nature of Python, some warnings may be incorrect; however, spurious |
| warnings should be fairly infrequent. |
| |
| *Pros:* Catches easy-to-miss errors like typos, use-vars-before-assignment, etc. |
| |
| *Cons:* `pychecker` isn't perfect. To take advantage of it, we'll need to |
| sometimes: a) Write around it b) Suppress its warnings c) Improve it or |
| d) Ignore it. |
| |
| *Decision:* Make sure you run `pychecker` on your code. |
| |
| To suppress warnings, you can set a module-level variable named |
| `__pychecker__` to suppress appropriate warnings. For example: |
| |
| {{{ |
| __pychecker__ = 'no-callinit no-classattr' |
| }}} |
| |
| Suppressing in this way has the advantage that we can easily search for |
| suppressions and revisit them. |
| |
| You can get a list of `pychecker` warnings by doing `pychecker --help`. |
| |
| Unused argument warnings can be suppressed by using `_` as the identifier |
| for the unused argument or prefixing the argument name with `unused_`. |
| In situations where changing the argument name is infeasible, you can |
| mention them at the begining of the function. For example: |
| |
| {{{ |
| def Foo(a, unused_b, unused_c, d=None, e=None): |
| d, e = (d, e) # silence pychecker |
| return a |
| }}} |
| |
| Ideally, `pychecker` would be extended to ensure that such |
| 'unused declarations' were true. |
| |
| You can find more information on the |
| [http://www.google.com/url?sa=D&q=http://pychecker.sourceforge.net PyChecker homepage]. |
| |
| == Imports == |
| |
| *What it is:* Mechanism for making use of code between modules. |
| |
| *Pros:* Very flexible relative to other languages. Packages, modules, classes, |
| functions, and fields all may be imported. |
| |
| *Cons:* `from foo import *` or `import bar.baz.Spar` is very nasty and can |
| lead to serious maintenance issues because it makes it hard to find module |
| dependencies. |
| |
| *Decision:* Import only modules. Use `as` to resolve name conflicts if |
| necessary. Use `from` for all imports below top-level. Use only absolute |
| imports; do not use relative imports. Do not import packages, classes, |
| functions, fields, or anything that is not a module. |
| |
| {{{ |
| import os |
| import sys |
| |
| from models.graphics import views as graphics_views |
| from models.sounds import views as sounds_views |
| from sound.effects import echo |
| ... |
| echo.echofilter(input, output, delay=0.7, atten=4) |
| }}} |
| |
| Even if the module is in the same package, do not directly import the module |
| without the full package name. This might cause the package to be imported |
| twice and have unintended side effects. |
| |
| == Exceptions == |
| |
| *What they are:* Exceptions are a means of breaking out of the normal flow |
| of control of a code block to handle errors or other exceptional conditions. |
| |
| *Pros:* The control flow of normal operation code is not cluttered by |
| error-handling code. It also allows the control flow to skip multiple |
| frames when a certain condition occurs, e.g., returning from N nested |
| functions in one step instead of having to carry-through error codes. |
| |
| *Cons:* May cause the control flow to be confusing. Easy to miss error |
| cases when making library calls. |
| |
| *Decision:* Exceptions are very Pythonic so we allow them, too, but only |
| as long as certain conditions are met: |
| |
| * Raise exceptions like this: `raise MyException("Error message")` or `raise MyException`. Do not use the two-argument form (`raise MyException, "Error message"`) or deprecated string-based exceptions (`raise "Error message"`). |
| * Modules or packages should define their own domain-specific base exception class, which should inherit from the built-in `Exception` class. The base exception for a module should be called `Error`. |
| |
| {{{ |
| class Error(Exception): |
| """Base exception for all exceptions raised in module Foo.""" |
| pass |
| }}} |
| |
| * Never use catch-all `except:` statements, or catch `Exception` or `StandardError`, unless you are re-raising the exception or in the outermost block in your thread (and printing an error message). Python is very tolerant in this regard and `except:` will really catch everything including Python syntax errors. It is easy to hide real bugs using `except:`. |
| * Minimize the amount of code in a `try/except` block. The larger the body of the `try`, the more likely that an exception will be raised by a line of code that you didn't expect to raise an exception. In those cases, the `try/except` block hides a real error. |
| * Use the `finally` clause to execute code whether or not an exception is raised in the `try` block. This is often useful for cleanup, i.e., closing a file. |
| |
| == Global variables == |
| |
| *What it is:* Variables that are declared at the module level. |
| |
| *Pros:* Occasionally useful. |
| |
| *Cons:* Has the potential to change module behavior during the import, |
| because assignments to module-level variables are done when the module is |
| imported. |
| |
| *Decision:* Avoid global variables in favor of class variables. Some |
| exceptions are: |
| |
| * Default options for scripts. |
| * Module-level constants. For example: `PI = 3.14159`. Constants should be named using all- caps with underscores; see [PythonStyleGuide#Naming Naming] below. |
| * It is sometimes useful for globals to cache values needed or returned by functions. |
| * If needed, globals should be made internal to the module and accessed through public module level functions; see [PythonStyleGuide#Naming Naming] below. |
| |
| == Nested Local Inner Classes and Functions == |
| |
| *What they are:* A class can be defined inside of a function or class. A |
| function can be defined inside a function. Nested functions have read-only |
| access to variables defined in enclosing scopes. |
| |
| *Pros:* Allows definition of utility classes and functions that are only |
| used inside of a very limited scope. Very ADT-y. |
| |
| *Cons:* Instances of nested or local classes cannot be pickled. |
| |
| *Decision:* They are fine. |
| |
| == List Comprehensions == |
| |
| *What they are:* List comprehensions and generator expressions provide a |
| concise and efficient way to create lists and iterators without resorting |
| to the use of `map()`, `filter()`, or `lambda`. |
| |
| *Pros:* Simple list comprehensions can be clearer and simpler than other |
| list creation techniques. Generator expressions can be very efficient, |
| since they avoid the creation of a list entirely. |
| |
| *Cons:* Complicated list comprehensions or generator expressions can be |
| hard to read. |
| |
| *Decision:* OK to use for one-liners, or when the `x for y in z` fits on one |
| line and a conditional on another (but see the example with the very-long |
| `x` below, which is a three-line case that is acceptable). Use loops |
| instead when things get more complicated. This is a judgment call. |
| |
| *No:* |
| |
| {{{ |
| # too complicated, use nested for loops instead |
| result = [(x, y) for x in range(10) |
| for y in range(5) |
| if x * y > 10] |
| }}} |
| |
| *Yes:* |
| |
| {{{ |
| # this case is complicated enough *not* to use a list comprehension |
| result = [] |
| for x in range(10): |
| for y in range(5): |
| if x * y > 10: |
| result.append((x, y)) |
| |
| # a nice, simple one-liner |
| squares = [x * x for x in range(10)] |
| |
| # a two-line generator (not list comprehension) case that is also OK |
| Eat(jelly_bean for jelly_bean in jelly_beans |
| if jelly_bean.color == 'black') |
| |
| # three-line case that is still debatably more readable than the equivalent loop |
| result = [someReallyLongWayToEatAJellyBean(jelly_bean) |
| for jelly_bean in jelly_beans |
| if jelly_bean != 'black'] |
| }}} |
| |
| == Default Iterators and Operators == |
| |
| *What they are:* Container types, like dictionaries and lists, define |
| default iterators and membership test operators (e.g `in` and `not in`). |
| |
| *Pros:* The default iterators and operators are simple and efficient. They |
| express the operation directly, without extra method calls. A function that |
| uses default operators is generic. It can be used with any type that |
| supports the operation. |
| |
| *Cons:* You can't tell the type of objects by reading the method names |
| (e.g. `has_key()` means a dictionary). This is also an advantage. |
| |
| *Decision:* Use default iterators and operators for types that support |
| them, like lists, dictionaries, and files. The built-in types define |
| iterator methods, too. Prefer these methods to methods that return |
| lists, except that you should not mutate a container while iterating |
| over it. |
| |
| *Yes:* |
| |
| {{{ |
| for key in adict: ... |
| |
| if key not in adict: ... |
| |
| if obj in alist: ... |
| |
| for line in afile: ... |
| |
| for k, v in dict.iteritems(): ... |
| }}} |
| |
| *No:* |
| |
| {{{ |
| for key in adict.keys(): ... |
| |
| if not adict.has_key(key): ... |
| |
| for line in afile.readlines(): ... |
| }}} |
| |
| == Generators == |
| |
| *What they are:* A generator function returns an iterator that yields a |
| value each time it executes a `yield` statement. After it yields a value, |
| the runtime state of the generator function is suspended until the next |
| value is needed. |
| |
| *Pros:* Simpler code, because the state of local variables and control |
| flow are preserved for each call. A generator uses less memory than a |
| function that creates an entire list of values at once. |
| |
| *Cons:* None. |
| |
| *Decision:* Fine. Use `"Yields:"` rather than `"Returns:"` in the |
| `__doc__` string for generator functions. |
| |
| == Using apply filter map reduce == |
| |
| *What they are*: Built-in functions useful for manipulating lists. |
| Commonly used in conjunction with `lambda` functions. |
| |
| *Pros:* Code is compact. |
| |
| *Cons:* Higher-order functional programming tends to be harder to understand. |
| |
| *Decision:* Use list comprehensions when possible and limit use of these |
| built-in functions to simple code and one-liners. In general, if such code |
| gets anywhere longer than 60-80 characters or if it uses multi-level function |
| calls (e.g., `map(lambda x: x[1], filter(...)))`, that's a signal that you |
| are better off writing a regular loop instead. Compare: |
| |
| *map/filter:* |
| |
| {{{ |
| map(lambda x:x[1], filter(lambda x:x[2] == 5, my_list)) |
| }}} |
| |
| *list comprehensions:* |
| |
| {{{ |
| [x[1] for x in my_list if x[2] == 5] |
| }}} |
| |
| == Lambda functions == |
| |
| *What they are:* Lambdas define anonymous functions in an expression, as |
| opposed to a statement. They are often used to define callbacks or |
| operators for higher-order functions like `map()` and `filter()`. |
| |
| *Pros:* Convenient. |
| |
| *Cons:* Harder to read and debug than local functions. The lack of names |
| means stack traces are more difficult to understand. Expressiveness is |
| limited because the function may only contain an expression. |
| |
| *Decision:* OK to use them for one-liners. If the code inside the `lambda` |
| function is any longer than 60-80 characters, it's probably better to define it |
| as a regular (nested) function. |
| |
| For common operations like addition, use the functions from the operator |
| module instead of `lambda` functions. For example, prefer `operator.add` |
| to `lambda x, y: x + y`. (The built-in `sum()` function would be better |
| than either alternative.) |
| |
| == Default Argument Values == |
| |
| *What they are:* You can specify values for variables at the end of a |
| function's parameter list, e.g., `def foo(a, b=0):`. If `foo` is called |
| with only one argument, `b` is set to `0`. If it is called with two |
| arguments, `b` has the value of the second argument. |
| |
| *Pros:* Often you have a function that uses lots of default values, |
| but _rarely_ you want to override the defaults. Default argument values |
| allow an easy way to do this, without having to define lots of functions |
| for the rare exceptions. Also, Python does not support overloaded |
| methods/functions and default arguments are an easy way of "faking" |
| the overloading behavior. |
| |
| *Cons:* Default arguments are evaluated once at module load time. This |
| may cause problems if the argument is a mutable object such as a list or |
| a dictionary. If the function modifies the object (e.g., by appending an |
| item to a list), the default value is modified. |
| |
| *Decision:* OK to use with the following caveats: |
| |
| * Do not use mutable objects as default values in the function or method definition. |
| |
| *Yes:* |
| |
| {{{ |
| def foo(a, b=None): |
| if b is None: |
| b = [] |
| }}} |
| |
| *No:* |
| |
| {{{ |
| def foo(a, b=[]): |
| ... |
| }}} |
| |
| Calling code must use named values for the default args. This helps |
| document the code somewhat and helps prevent and detect interface |
| breakage when more arguments are added. |
| |
| {{{ |
| def foo(a, b=1): |
| ... |
| }}} |
| |
| *Yes:* |
| |
| {{{ |
| foo(1) |
| foo(1, b=2) |
| }}} |
| |
| *No:* |
| |
| {{{ |
| foo(1, 2) |
| }}} |
| |
| == Properties == |
| |
| *What they are:* A way to wrap method calls for getting and setting an |
| attribute as a standard attribute access when the computation is lightweight. |
| |
| *Pros:* Readability is increased by eliminating explicit `get` and `set` |
| method calls for simple attribute access. Allows calculations to be lazy. |
| Considered the Pythonic way to maintain the interface of a class. In terms |
| of performance, allowing properties bypasses needing trivial accessor |
| methods when a direct variable access is reasonable while allowing future |
| accessor methods to be possible without breaking the interface. |
| |
| *Cons:* Properties are specified after the getter and setter methods are |
| declared, requiring one to notice they are used for properties farther down |
| in the code (except for read-only properties created with the `@property` |
| decorator - see below). Must inherit from object. Can hide side-effects |
| much like operator overloading. Can be confusing for subclasses. |
| |
| *Decision:* Use properties in code where you are accessing or setting |
| data where you would normally have used simple, lightweight accessor or |
| setter methods. Read-only properties should be created with the |
| `@property` [PythonStyleGuide#Function_and_Method_Decorators decorator]. |
| |
| Inheritance with properties can be non-obvious if the property itself |
| is not overridden. Thus one must make sure that accessor methods are |
| called indirectly to ensure methods overridden in subclasses are called |
| by the property (using the Template Method design pattern). |
| |
| *Yes:* |
| |
| {{{ |
| import math |
| |
| class Square(object): |
| """Basic square with writable 'area' property, read-only 'perimeter' property. |
| |
| To use: |
| >>> sq = Square(3) |
| >>> sq.area |
| 9 |
| >>> sq.perimeter |
| 12 |
| >>> sq.area = 16 |
| >>> sq.side |
| 4 |
| >>> sq.perimeter |
| 16 |
| """ |
| |
| def __init__(self, side): |
| self.side = side |
| |
| def _getArea(self): |
| """Calculation for 'area' property""" |
| return self.side ** 2 |
| |
| def __getArea(self): |
| """Indirect accessor for 'area' property""" |
| return self._getArea() |
| |
| def _setArea(self, area): |
| """Setter for 'area' property""" |
| self.side = math.sqrt(area) |
| |
| def __setArea(self, area): |
| """Indirect setter for 'area' property""" |
| self._setArea(area) |
| |
| area = property(__getArea, __setArea, |
| doc="""Get or set the area of the square""") |
| |
| @property |
| def perimeter(self): |
| return self.side * 4 |
| }}} |
| |
| == True False evaluations == |
| |
| *What it is:* Python evaluates certain values as "false" when in a boolean |
| context. A quick "rule of thumb" is that all "empty" values are considered |
| "false" so `0`, `None`, `[]`,` {}`, `""` all evaluate as "false" in a |
| boolean context. |
| |
| *Pros:* Conditions using Python booleans are easier to read and less |
| error-prone. In most cases, it's also faster. |
| |
| *Cons:* May look strange to C/C++ developers. |
| |
| *Decision:* Use the "implicit" false if at all possible, e.g., |
| `if foo:` rather than `if foo != []:`. There are a few caveats that you |
| should keep in mind though: |
| |
| * Comparisons to singletons like `None` should always be done with `is` or `is not`. Also, 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 be a value that's false in a boolean context! |
| * For sequences (strings, lists, tuples), use the fact that empty sequences are false, so `if not seq:` or `if seq:` is preferable to `if len(seq):` or `if not len(seq):`. |
| * Note that `'0'` (i.e., 0 as string) evaluates to true. |
| |
| == Boolean built in type == |
| |
| *What it is:* A boolean type has been available in Python since version 2.3. |
| Two new built-in constants were added: `True` and `False`. |
| |
| *Pros:* It makes code easier to read and is backward-compatible with the |
| use of integers as boolean in previous versions. |
| |
| *Cons:* None. |
| |
| *Decision:* Use booleans. |
| |
| == String Methods == |
| |
| *What they are:* String objects include methods for functions that used to |
| be in the `string` module. |
| |
| *Pros:* No need to import the `string` module; methods work with both |
| regular byte-strings and unicode-strings. |
| |
| *Cons:* None. |
| |
| *Decision:* Use them. The `string` module is deprecated in favor of |
| string methods. |
| |
| *No:* `words = string.split(foo, ':')` |
| |
| *Yes:* `words = foo.split(':')` |
| |
| == Lexical Scoping == |
| |
| *What it is:* A nested Python function can refer to variables defined |
| in enclosing functions, but can not assign to them. Variable bindings are |
| resolved using lexical scoping, that is, based on the static program text. |
| Any assignment to a name in a block will cause Python to treat all |
| references to that name as a local variable, even if the use precedes |
| the assignment. If a global declaration occurs, the name is treated as a |
| global variable. |
| |
| An example of the use of this feature is: |
| |
| {{{ |
| def getAdder(summand1): |
| """getAdder returns a function that adds numbers to a given number.""" |
| def anAdder(summand2): |
| return summand1 + summand2 |
| |
| return anAdder |
| }}} |
| |
| *Pros:* Often results in clearer, more elegant code. Especially comforting |
| to experienced Lisp and Scheme (and Haskell and ML and ...) programmers. |
| |
| *Cons:* None. |
| |
| *Decision:* Okay to use. |
| |
| == Function and Method Decorators == |
| |
| *What they are:* Decorators for Functions and Methods, added in Python 2.4 |
| (a.k.a "the `@` notation"). The most common decorators are `@classmethod` |
| and `@staticmethod`, for converting ordinary methods to class or static |
| methods. However, the decorator syntax allows for user-defined decorators |
| as well. Specifically, for some function `myDecorator`, this: |
| |
| {{{ |
| class C(object): |
| @myDecorator |
| def aMethod(self): |
| # method body ... |
| }}} |
| |
| is equivalent to: |
| |
| {{{ |
| class C(object): |
| def aMethod(self): |
| # method body ... |
| aMethod = myDecorator(aMethod) |
| }}} |
| |
| *Pros:* Elegantly specifies some transformation on a method; the |
| transformation might eliminate some repetitive code, enforce invariants, etc. |
| |
| *Cons:* Decorators can perform arbitrary operations on a function's |
| arguments or return values, resulting in surprising implicit behavior. |
| Additionally, decorators execute at import time. Failures in decorator code |
| are pretty much impossible to recover from. |
| |
| *Decision:* Use decorators judiciously when there is a clear advantage. |
| Decorators should follow the same import and naming guidelines as functions. |
| Decorator `__doc__` string should clearly state that the function is a |
| decorator. Write unit tests for decorators. |
| |
| Avoid external dependencies in the decorator itself (e.g. don't rely on |
| files, sockets, database connections, etc.), since they might not be |
| available when the decorator runs (at import time, perhaps from `pychecker` |
| or other tools). A decorator that is called with valid parameters should |
| (as much as possible) be guaranteed to succeed in all cases. |
| |
| Decorators are a special case of "top level code" - see |
| [PythonStyleGuide#Main Main] for more discussion. |
| |
| == Threading == |
| |
| Threading |
| [http://code.google.com/appengine/kb/general.html#libraries is not available in Google App Engine], |
| so do not use it in the SoC framework or Melange web applications. |
| |
| == Power features == |
| |
| *What it is:* Python is an extremely flexible language and gives you |
| many fancy features such as metaclasses, access to bytecode, on-the-fly |
| compilation, dynamic inheritance, object reparenting, import hacks, |
| reflection, modification of system internals, etc. |
| |
| *Pros:* These are powerful language features. They can make your code |
| more compact. |
| |
| *Cons:* It's very tempting to use these "cool" features when they're not |
| absolutely necessary. It's harder to read, understand, and debug code |
| that's using unusual features underneath. It doesn't seem that way at |
| first (to the original author), but when revisiting the code, it tends |
| to be more difficult than code that is longer but is straightforward. |
| |
| *Decision:* Avoid these features in Melange code. Discuss exceptions on the |
| [MailingListsGuidelines#Developer_list developer mailing list]. |
| |
| = Python Style Rules = |
| |
| == Semicolons == |
| |
| Do not terminate your lines with semi-colons and do not use semi-colons |
| to put two commands on the same line. |
| |
| == Line length == |
| |
| Maximum line length is 80 characters. |
| |
| *Exception:* lines importing modules may end up longer than 80 characters. |
| |
| Make use of Python's implicit line joining inside parentheses, brackets |
| and braces. If necessary, you can add an extra pair of parentheses around |
| an expression. |
| |
| *Yes:* |
| |
| {{{ |
| fooBar(self, width, height, color='black', design=None, x='foo', |
| emphasis=None, highlight=0) |
| |
| |
| if ((width == 0) and (height == 0) |
| and (color == 'red') and (emphasis == 'strong')): |
| }}} |
| |
| When a literal string won't fit on a single line, use parentheses for |
| implicit line joining. |
| |
| {{{ |
| x = ('This will build a very long long ' |
| 'long long long long long long string') |
| }}} |
| |
| Make note of the indentation of the elements in the line continuation |
| examples above; see the |
| [PythonStyleGuide#Indentation indentation section] for explanation. |
| |
| == Parentheses == |
| |
| Use parentheses sparingly. Do not use them: |
| |
| * in `return` statements |
| * in conditional statements unless using parentheses for implied line continuation (see above) |
| * around tuples, unless they are necessary syntactically or for clarity |
| |
| It is, however, fine to use parentheses: |
| |
| * for implied line continuation |
| * around sub-expressions in a larger expression (including the sub-expressions that are part of a conditional statement) |
| |
| In fact, parentheses around sub-expressions is preferred to relying solely |
| on operator precedence. |
| |
| *Yes:* |
| |
| {{{ |
| if foo: |
| |
| while x: |
| |
| if x and y: |
| |
| if not x: |
| |
| if (x < 3) and (not y): |
| |
| return foo |
| |
| for x, y in dict.items(): |
| |
| x, (y, z) = funcThatReturnsNestedTuples() |
| }}} |
| |
| *No:* |
| |
| {{{ |
| if (x): |
| |
| while (x): |
| |
| if not(x): |
| |
| if ((x < 3) and (not y)): |
| |
| return (foo) |
| |
| for (x, y) in dict.items(): |
| |
| (x, (y, z)) = funcThatReturnsNestedTuples() |
| }}} |
| |
| == Indentation == |
| |
| _Note that this differs from |
| [http://www.python.org/dev/peps/pep-0008/ PEP8] |
| and instead follows the original Google Python Style guide from which |
| this style guide originated._ |
| |
| Indent your code blocks with 2 spaces. Never use tabs or mix tabs and |
| spaces. In cases of implied line continuation, you should align wrapped |
| elements either vertically, as per the examples in the line length |
| section; or using a hanging indent of *4* spaces (not 2, so as not to be |
| confused with an immediately-following nested block), in which case there |
| should be no argument on the first line. |
| |
| *Yes:* |
| |
| {{{ |
| # Aligned with opening delimiter |
| foo = longFunctionName(var_one, var_two, |
| var_three, var_four) |
| |
| # 4-space hanging indent; nothing on first line |
| foo = longFunctionName( |
| var_one, var_two, var_three, |
| var_four) |
| }}} |
| |
| *No:* |
| |
| {{{ |
| # Stuff on first line forbidden |
| foo = longFunctionName(var_one, var_two, |
| var_three, var_four) |
| |
| # 2-space hanging indent forbidden |
| foo = longFunctionName( |
| var_one, var_two, var_three, |
| var_four) |
| }}} |
| |
| == Blank lines == |
| |
| Two blank lines between top-level definitions, be they function or class |
| definitions. One blank line between method definitions and between the |
| class line and the first method. One blank line between |
| [PythonStyleGuide#Doc_strings `__doc__` strings] and the code that follows |
| them. Use single blank lines as you judge appropriate within functions or |
| methods. |
| Always have a single blank line at the end of the file, this suppresses the "\ No newline at end of file" message that is generated by most diff tools. |
| |
| == Whitespace == |
| |
| No whitespace inside parentheses, brackets or braces. |
| |
| *Yes:* `spam(ham[1], {eggs: 2}, [])` |
| |
| *No:* `spam( ham[ 1 ], { eggs: 2 }, [ ] )` |
| |
| No whitespace before a comma, semicolon, or colon. _Do_ use whitespace |
| after a comma, semicolon, or colon except at the end of the line. |
| |
| *Yes:* |
| |
| {{{ |
| if x == 4: |
| |
| print x, y |
| |
| x, y = y, x |
| }}} |
| |
| *No:* |
| |
| {{{ |
| if x == 4 : |
| |
| print x , y |
| |
| x , y = y , x |
| }}} |
| |
| No whitespace before the open paren/bracket that starts an argument |
| list, indexing or slicing. |
| |
| *Yes:* `spam(1)` |
| |
| *No:* `spam (1)` |
| |
| *Yes:* `dict['key'] = list[index]` |
| |
| *No:* `dict ['key'] = list [index]` |
| |
| Surround binary operators with a single space on either side for |
| assignment (`=`), comparisons (`==`, `<`, `>`, `!=`, `<>`, `<=`, `>=`, |
| `in`, `not in`, `is`, `is not`), and booleans (`and`, `or`, `not`). Use |
| your better judgment for the insertion of spaces around arithmetic |
| operators but always be consistent about whitespace on either side of |
| a binary operator. |
| |
| *Yes:* `x == 1` |
| |
| *No:* `x<1` |
| |
| Don't use spaces around the '`=`' sign when used to indicate a keyword |
| argument or a default parameter value. |
| |
| *Yes:* `def Complex(real, imag=0.0): return Magic(r=real, i=imag)` |
| |
| *No:* `def Complex(real, imag = 0.0): return Magic(r = real, i = imag)` |
| |
| === Python Interpreter == |
| |
| Modules should begin with a "shebang" line specifying the Python |
| interpreter used to execute the program: |
| |
| `#!/usr/bin/python2.5` |
| |
| [http://code.google.com/appengine/docs/python/purepython.html Google App Engine requires Python 2.5]. |
| |
| == Comments == |
| |
| === Doc strings === |
| |
| Python has a unique commenting style using `__doc__` strings. A `__doc__` |
| string is a string that is the first statement in a package, module, |
| class or function. These strings can be extracted automatically through |
| the `__doc__()` member of the object and are used by `pydoc`. (Try |
| running `pydoc` on your module to see how it looks.) Our convention for |
| `__doc__` strings is to use the three double-quote format for strings. |
| A `__doc__` string should be organized as a summary line (one physical |
| line, [PythonStyleGuide#Line_length 80 characters or less]) terminated |
| by a period, followed by a blank line, followed by the rest of the |
| `__doc__` string starting at the same cursor position as the first quote |
| of the first line. There are more formatting guidelines for `__doc__` |
| strings below. |
| |
| === Modules === |
| |
| Every file should contain a block comment with a copyright notice and |
| license statement at the top of the file. |
| |
| ==== Copyright and license notices ==== |
| |
| {{{ |
| #!/usr/bin/python2.5 |
| # |
| # Copyright [current year] the Melange authors. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| }}} |
| |
| This should be followed by a `__doc__` string describing the contents |
| of the module. Author information is then included after this string. |
| If an optional email is provided, then the entire author string |
| added to the `__authors__` list needs to be an |
| [http://www.ietf.org/rfc/rfc2821.txt RFC 2821 compliant] email address. |
| |
| ==== Module header and authors ==== |
| |
| {{{ |
| """A one line summary of the module or script, terminated by a period. |
| |
| Leave one blank line. The rest of this __doc__ string should contain an |
| overall description of the module or script. Optionally, it may also |
| contain a brief description of exported classes and functions. |
| |
| ClassFoo: One line summary. |
| functionBar(): One line summary. |
| """ |
| |
| __authors__ = [ |
| # alphabetical order by last name, please |
| '"John Smith" <johnsmith@example.com>', |
| '"Joe Paranoid" <joeisgone@example.com>', # email address is required |
| ] |
| }}} |
| |
| If a new contributor is not yet present in the |
| [http://soc.googlecode.com/svn/trunk/AUTHORS AUTHORS file], that contributor |
| should be added to that file as part of the first commit from that |
| contributor. |
| |
| === Functions and Methods === |
| |
| Any function or method which is not both obvious and very short needs |
| a `__doc__` string. Additionally, any externally accessible function |
| or method regardless of length or simplicity needs a `__doc__` string. |
| The `__doc__` string should include what the function does and have |
| detailed descriptions of the input ("`Args:`") and output |
| ("`Returns:`", "`Raises:`", or "`Yields:`"). The `__doc__` string |
| should give enough information to write a call to the function without |
| looking at a single line of the function's code. The `__doc__` string |
| should specify the expected types where specific types are required, |
| and it should mention any default argument values. A "`Raises:`" section |
| should list all exceptions that can be raised by the function. The |
| `__doc__` string for generator functions should use "`Yields:`" rather |
| than "`Returns:`". |
| |
| The function or method `__doc__` string should not, generally, describe |
| implementation details unless it's some complicated algorithm. For |
| tricky code, block/inline comments within the code are more appropriate. |
| |
| {{{ |
| def fetchRows(table, keys): |
| """Fetch rows from a table. |
| |
| Args: |
| table: An open table.Table instance. |
| keys: A sequence of strings representing the key of each table |
| row to fetch. |
| |
| Returns: |
| A dict mapping keys to the corresponding table row data |
| fetched. Each row is represented as a tuple of strings. For |
| example: |
| |
| {'Serak': ('Rigel VII', 'Preparer'), |
| 'Zim': ('Irk', 'Invader'), |
| 'Lrrr': ('Omicron Persei 8', 'Emperor')} |
| |
| If a key from the keys argument is missing from the dictionary, |
| then that row was not found in the table. |
| |
| Raises: |
| IOError: An error occurred accessing the table.Table object. |
| """ |
| pass |
| }}} |
| |
| === Classes === |
| |
| Classes should have a `__doc__` string below the class definition |
| describing the class. If your class has public attributes they should |
| be documented here in an `Attributes:` section. |
| |
| {{{ |
| class SampleClass(object): |
| |
| """Summary of class here. |
| |
| Longer class information.... |
| Longer class information.... |
| |
| Attributes: |
| likes_spam: A boolean indicating if we like SPAM or not. |
| eggs: An integer count of the eggs we have laid. |
| """ |
| |
| def __init__(self, likes_spam=False): |
| """Inits SampleClass with blah. |
| |
| Args: |
| likes_spam: Initial indication of if the SampleClass |
| instance likes SPAM or not (default is False) |
| """ |
| self.likes_spam = likes_spam |
| self.eggs = 0 |
| |
| def publicMethod(self): |
| """Perform operation blah.""" |
| pass |
| }}} |
| |
| === Block and Inline Comments === |
| |
| The final place to have comments is in tricky parts of the code. If |
| you're going to have to explain it at the next code review, you should |
| comment it now. Complicated operations get a few lines of comments |
| before the operations commence. Non-obvious ones get comments at the |
| end of the line. |
| |
| {{{ |
| # We use a weighted dictionary search to find out where i is in |
| # the array. We extrapolate position based on the largest number |
| # in the array and the array size and then do binary search to |
| # get the exact number. |
| |
| if i & (i-1) == 0: # true iff i is a power of 2 |
| }}} |
| |
| These comments should be separated from the code to improve legibility. |
| Block comments should be preceded by a blank line. In general, |
| end-of-line comments should be at least 2 spaces away from the code. These |
| end-of-line comments _can_ be lined up if there are many in a row (or |
| in a function), but this is not required. |
| |
| On the other hand, never describe the code. Assume the person reading |
| the code knows Python (though not what you're trying to do) better |
| than you do. |
| |
| {{{ |
| # BAD COMMENT: Now go through the b array and make sure whenever i occurs |
| # the next element is i+1 |
| }}} |
| |
| == Classes == |
| |
| If a class inherits from no other base classes, explicitly inherit from |
| `object`. This also applies to nested classes. |
| |
| *No:* |
| |
| {{{ |
| class SampleClass: |
| pass |
| |
| class OuterClass: |
| class InnerClass: |
| pass |
| }}} |
| |
| *Yes:* |
| |
| {{{ |
| class SampleClass(object): |
| pass |
| |
| class OuterClass(object): |
| class InnerClass(object): |
| pass |
| |
| class ChildClass(ParentClass): |
| """Explicitly inherits from another class already.""" |
| pass |
| }}} |
| |
| Inheriting from `object` is needed to make properties work properly, and |
| it will protect our code from one particular flavor of things that might |
| break once we switch to Python 3000. It also defines special methods that |
| implement the default semantics of objects including `__new__`, |
| `__init__`, `__delattr__`, `__getattribute__`, `__setattr__`, `__hash__`, |
| `__repr__`, and `__str__`. |
| |
| == Strings == |
| |
| Use the `%` operator for formatting strings, even when the parameters |
| are all strings. Use your best judgement to decide between `+` and `%` |
| though. |
| |
| *No:* |
| |
| {{{ |
| x = '%s%s' % (a, b) # use + in this case |
| x = imperative + ', ' + expletive + '!' |
| x = 'name: ' + name + '; score: ' + str(n) |
| }}} |
| |
| *Yes:* |
| |
| {{{ |
| x = a + b |
| x = '%s, %s!' % (imperative, expletive) |
| x = 'name: %s; score: %d' % (name, n) |
| }}} |
| |
| Avoid using the `+` and `+=` operators to accumulate a string within |
| a loop. Since strings are immutable, this creates unnecessary temporary |
| objects and results in quadratic rather than linear running time. |
| Instead, add each sub-string to a `list` and `''.join()` that list after |
| the loop terminates. |
| |
| *No:* |
| |
| {{{ |
| employee_table = '<table>' |
| for last_name, first_name in employee_list: |
| employee_table += '<tr><td>%s, %s</td></tr>' % (last_name, first_name) |
| employee_table += '</table>' |
| }}} |
| |
| *Yes:* |
| |
| {{{ |
| items = ['<table>'] |
| for last_name, first_name in employee_list: |
| items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name)) |
| items.append('</table>') |
| employee_table = ''.join(items) |
| }}} |
| |
| Use `"""` for multi-line strings rather than `'''`. Note, however, that |
| it is often cleaner to use implicit line joining since multi-line |
| strings do not flow with the indentation of the rest of the program: |
| |
| *No:* |
| {{{ |
| print """This is pretty ugly. |
| Don't do this. |
| """ |
| }}} |
| |
| *Yes:* |
| |
| {{{ |
| print ("This is much nicer.\n" |
| "Do it this way.\n") |
| }}} |
| |
| == TODO style == |
| |
| Use `TODO` comments for code that is temporary, a short-term solution, |
| or good-enough but not perfect. |
| |
| `TODO`s should include the string `TODO` in all caps, followed by your |
| `username` in parentheses: `TODO(username)`. A colon is optional. The |
| main purpose is to have a consistent `TODO` format searchable by `username`. |
| |
| {{{ |
| # TODO(someuser): Use a "*" here for concatenation operator. |
| # TODO(anotheruser) change this to use relations. |
| }}} |
| |
| If your `TODO` is of the form "At a future date do something" make sure |
| that you either include a very specific date ("Fix by November 2008") |
| or a very specific event ("Remove this code after the Foo entities in |
| the datastore have all added the new fubar property."). |
| |
| == Imports grouping and order == |
| |
| Imports should be on separate lines, e.g.: |
| |
| *Yes:* |
| |
| {{{ |
| import os |
| import sys |
| }}} |
| |
| *No:* |
| |
| {{{ |
| import sys, os |
| }}} |
| |
| Imports are always put at the top of the file, just after any module |
| comments and `__doc__` strings and before module globals and constants. |
| Imports should be grouped with the order being most generic to least |
| generic: |
| |
| * standard library imports |
| * third-party library imports |
| * Google App Engine imports |
| * django framework imports |
| * SoC framework imports |
| * SoC-based module imports |
| * application specific imports |
| |
| Sorting should be done alphabetically. |
| |
| {{{ |
| import a_standard |
| import b_standard |
| |
| import a_third_party |
| import b_third_party |
| |
| from a_soc import f |
| from a_soc import g |
| from b_soc import d |
| }}} |
| |
| == Statements == |
| |
| Generally only one statement per line. However, you may put the result |
| of a test on the same line as the test only if the entire statement |
| fits on one line. In particular, you can never do so with `try/except` |
| since the `try` and `except` can't both fit on the same line, and you |
| can only do so with an `if` if there is no `else`. |
| |
| *Yes:* |
| |
| {{{ |
| if foo: fuBar(foo) |
| }}} |
| |
| *No:* |
| |
| {{{ |
| if foo: fuBar(foo) |
| else: fuBaz(foo) |
| |
| try: fuBar(foo) |
| except ValueError: fuBaz(foo) |
| |
| try: |
| fuBar(foo) |
| except ValueError: fuBaz(foo) |
| }}} |
| |
| == Access control == |
| |
| If an accessor function would be trivial you should use public variables |
| instead of accessor functions to avoid the extra cost of function calls |
| in Python. When more functionality is added you can use property to keep |
| the syntax consistent. |
| |
| On the other hand, if access is more complex, or the cost of accessing |
| the variable is significant, you should use function calls (following |
| the [PythonStyleGuide#Naming Naming guidelines]) such as `getFoo()` and |
| `setFoo()`. If the past behavior allowed access through a property, do |
| not bind the new accessor functions to the property. Any code still |
| attempting to access the variable by the old method should break visibly |
| so callers are made aware of the change in complexity. |
| |
| == Naming == |
| |
| === Names to avoid === |
| |
| * single character names, except for counters or iterators |
| * dashes (`-`) in any package/module name |
| * `__double_leading_and_trailing_underscore__` names (reserved by Python) |
| |
| === Naming convention === |
| |
| _Note that some naming conventions differ from |
| [http://www.python.org/dev/peps/pep-0008/ PEP8] |
| and instead follow the original Google Python Style guide from which |
| this style guide originated._ |
| |
| * "Internal" means internal to a module or protected or private within a class. |
| * Prepending a single underscore (`_`) has some support for protecting module variables and functions (not included with `import * from`). |
| * Prepending a double underscore (`__`) to an instance variable or method effectively serves to make the variable or method private to its class (using name mangling). |
| * Place related classes and top-level functions together in a module. Unlike Java, there is no need to limit yourself to one class per module. However, make sure the classes and top-level functions in the same module have [http://en.wikipedia.org/wiki/Cohesion_(computer_science) high cohesion]. |
| * Use `CapWords` for class names, but `lower_with_under.py` for module names. |
| |
| === Naming examples === |
| |
| || *Type* || *Public* || *Internal* || |
| || _Packages_ || `lower_with_under` || || |
| || _Modules_ || `lower_with_under` || `_lower_with_under` || |
| || _Classes_ || `CapWords` || `_CapWords` || |
| || _Exceptions_ || `CapWords` || || |
| || _Functions_ || `firstLowerCapWords()` || `_firstLowerCapWords()` || |
| || _Global/Class Constants_ || `CAPS_WITH_UNDER` || `_CAPS_WITH_UNDER` || |
| || _Global/Class Variables_ || `lower_with_under` || `_lower_with_under` || |
| || _Instance Variables_ || `lower_with_under` || `_lower_with_under` _(protected)_ or `__lower_with_under` _(private)_ || |
| || _Method Names_^*^ || `firstLowerCapWords()` || `_firstLowerCapWords()` _(protected)_ or `__firstLowerCapWords()` _(private)_ || |
| || _Function/Method Parameters_ || `lower_with_under` || || |
| || _Local Variables_ || `lower_with_under` || || |
| |
| ^*^ Consider just using |
| [PythonStyleGuide#Access_control direct access to public attributes] |
| in preference to getters and setters, as function calls are expensive |
| in Python, and `property` can be used later to turn attribute access into a |
| function call without changing the access syntax. |
| |
| == Main == |
| |
| Every Python source file should be importable. In Python, `pychecker`, |
| `pydoc`, and unit tests require modules to be importable. Your code |
| should always check `if __name__ == '__main__':` before executing your |
| main program so that the main program is not executed when the module |
| is imported. The capitalization of `main()` is intentionally inconsistent |
| with the rest of the naming conventions, which would suggest `Main()`. |
| |
| {{{ |
| if __name__ == '__main__': |
| # parse arguments |
| main() |
| }}} |
| |
| All code at the top level will be executed when the module is imported. |
| Be careful not to call functions, create objects, or perform other |
| operations that should not be executed when the file is being `pycheck`ed |
| or `pydoc`ed. |
| |
| == Conclusion == |
| |
| _BE CONSISTENT._ |
| |
| If you are editing code, take a few minutes to look at the code around |
| you and determine its style. If spaces are used around the `if` clauses, |
| you should, too. If the comments have little boxes of stars around them, |
| make your comments have little boxes of stars around them, too. |
| |
| The point of having style guidelines is to have a common vocabulary |
| of coding so people can concentrate on what you are saying rather than |
| on how you are saying it. We present global style rules here so people |
| know the vocabulary, but local style is also important. If code you add |
| to a file looks drastically different from the existing code around it, |
| it throws readers out of their rhythm when they go to read it. Try to |
| avoid this. |
| |
| ---- |
| _Copyright 2008 Google Inc._ |
| _This work is licensed under a_ |
| [http://soc.googlecode.com/svn/wiki/html/licenses/cc-by-attribution-2_5.html Creative Commons Attribution 2.5 License]. |
| [http://creativecommons.org/licenses/by/2.5/ http://soc.googlecode.com/svn/wiki/html/licenses/cc-by-2_5-88x31.png] |