| #summary Style guide for Python code contributed to Melange |
| #labels Contents-Draft,Phase-Guidelines,Importance-Featured,Featured |
| |
| Melange follows the [http://google-styleguide.googlecode.com/svn/trunk/pyguide.html Google Python Style Guide]; this document describes only those respects in which Melange's style differs from what is laid out in that document. |
| |
| 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]). The Google Python Style Guide and these amendments to it are 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 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#Imports Imports]: _Import only modules and only by name *(no wildcard imports)*_ |
| # [PythonStyleGuide#Function_Arguments Function Arguments]: _Pass positional arguments positionally and keyword arguments by keyword._ |
| # [PythonStyleGuide#Threading Threading]: _*For now, do not use* (but it is on its way as part of [https://code.google.com/p/soc/issues/detail?id=1596 issue 1596])_ |
| |
| == 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]: _Variable, either omitted, `#!/usr/bin/python`, or `#!/usr/bin/python2.7`_ |
| # [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 = |
| |
| == 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. |
| |
| == Function Arguments == |
| |
| *What they are:* Arguments passed to functions either by position or by name. |
| |
| *Pros:* Passing arguments always by name can help code be self-documenting. |
| |
| *Cons:* Passing positional arguments by name can make a call site appear as |
| though all arguments are optional. Passing keyword arguments by position can |
| make a call site appear as though all arguments are required. |
| |
| *Decision:* Always pass positional arguments positionally and keyword |
| arguments by keyword. |
| |
| == Threading == |
| |
| Melange as of January 2013 is not thread-safe. Work to support thread safety |
| is happening as part of [https://code.google.com/p/soc/issues/detail?id=1596 |
| issue 1596], but for now avoid threading. |
| |
| = 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 which are not intended for direct execution (and which have no effect if executed) should not include a shebang line. |
| |
| Modules intended for direct execution should begin with a shebang line specifying the Python interpreter used to execute the program, most likely `#!/usr/bin/python` or `#!/usr/bin/python2.7`. |
| |
| == 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] |