1. Semicolons
Do not terminate your lines with semi-colons and do not use semi-colons to put two commands on the same line.
2. Line Length
Maximum line length is 80 characters.
Exception: lines importing modules may end up longer than 80 characters only if using Python 2.4 or earlier.
Do not use backslash line continuation.
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: foo_bar(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 '
3. Parenthesis
It is not C++: Use parentheses sparingly.
Do not use them in return statements or conditional statements unless using parentheses for implied line continuation. (See above.) It is however fine to use parentheses around tuples.
Yes: if foo: bar() while x: x = bar() if x and y: bar() if not x: bar() return foo for (x, y) in dict.items(): ...
No: if (x): bar() if not(x): bar() return (foo)
4. Indentation
Indent your code blocks with 4 spaces. (PyCharm does not use tab character by default, you can use tab but Pycharm interpreted as spaces rather than tab character)
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, in which case there should be no argument on the first line.
# 4-space hanging indent; nothing on first line foo = long_function_name( var_one, var_two, var_three, var_four)
No: # Stuff on first line forbidden foo = long_function_name(var_one, var_two, var_three, var_four) # 2-space hanging indent forbidden foo = long_function_name( var_one, var_two, var_three, var_four)
5. Blank Line
Two blank lines between top-level definitions, one blank line between method definitions.
6. Whitespace
Follow standard typographic rules for the use of spaces around punctuation.
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 BOOLEAN
No: x<1
Don't use spaces around the '=' sign when used to indicate a keyword argument or a default parameter value.
But for normal assignment "leave space"
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)
Don't use spaces to vertically align tokens on consecutive lines, since it becomes a maintenance burden (applies to
:
, #
, =
, etc.):Yes: foo = 1000 # comment long_name = 2 # comment that should not be aligned dictionary = { 'foo': 1, 'long_name': 2, }
No: foo = 1000 # comment long_name = 2 # comment that should not be aligned dictionary = { 'foo' : 1, 'long_name': 2, }
7. Shebang Line
#!/usr/bin/python
.
normally no need
8. Comment
Be sure to use the right style for module, function, method and in-line 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) terminated by a period, question mark, or exclamation point, 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.
""" XXXXXXXXXXXXXXXXXXXXX."""
blank line
<body>
.....
</body>
Modules (current no need for me)
Every file should contain license boilerplate. Choose the appropriate boilerplate for the license used by the project (for example, Apache 2.0, BSD, LGPL, GPL)
Functions and Methods
As used in this section "function" applies to methods, function, and generators.
A function must have a docstring, UNLESS it meets all of the following criteria:
- not externally visible
- very short
- obvious
Guideline for docstring of a function. A docstring should give enough information to write a call to the function without reading the function's code. A docstring should describe the function's calling syntax and its semantics, not its implementation. For tricky code, comments alongside the code are more appropriate than using docstrings.
Certain aspects of a function should be documented in special sections, listed below. Each section begins with a heading line, which ends with a colon. Sections should be indented two spaces, except for the heading.
- Args:
- List each parameter by name. A description should follow the name, and be separated by a colon and a space. If the description is too long to fit on a single 80-character line, use a hanging indent of 2 or 4 spaces (be consistent with the rest of the file).The description should mention required type(s) and the meaning of the argument.
If a function accepts *foo (variable length argument lists) and/or **bar (arbitrary keyword arguments), they should be listed as *foo and **bar. - Returns: (or Yields: for generators)
- Describe the type and semantics of the return value. If the function only returns None, this section is not required.
- Raises:
- List all exceptions that are relevant to the interface.
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None): """Fetches rows from a Bigtable. Retrieves rows pertaining to the given keys from the Table instance represented by big_table. Silly things may happen if other_silly_variable is not None. Args: big_table: An open Bigtable Table instance. keys: A sequence of strings representing the key of each table row to fetch. other_silly_variable: Another optional variable, that has a much longer name than the other args, and which does nothing. 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 bigtable.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 and follow the same formatting as a function's Args 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.""" self.likes_spam = likes_spam self.eggs = 0 def public_method(self): """Performs operation blah."""
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.
# We use a weighted dictionary search to find out where i is in # the array. We extrapolate position based on the largest num # in the array and the array size and then do binary search to # get the exact number. Complicated operations get a few lines of comments before the operations commence. if i & (i-1) == 0: # true iff i is a power of 2 Non-obvious ones get comments at the end of the line.
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
^
Do not describe the code: The assumption here is that reader of your codes know how Python works, and I cannot insult the IQ of the reader by describing trivial things
Currently, the only thing that you need to do is to write the docstring summary line. Other detailed comments are not required when developing, but are when publishing
9. String Formatting
Use the
%
operator for formatting strings, even when the parameters are all strings. Use your best judgement to decide between +
and %
though.- use + when it is straightforward
- use % formatting when it is complicated
Yes: x = a + b x = '%s, %s!' % (imperative, expletive) x = 'name: %s; score: %d' % (name, n)
No: x = '%s%s' % (a, b) # use + in this case x = imperative + ', ' + expletive + '!' x = 'name: ' + name + '; score: ' + str(n)
+
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 substring to a list and ''.join
the list after the loop terminates (or, write each substring to a cStringIO.StringIO
buffer).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)
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>'
"""
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:Yes:
print ("This is much nicer.\n" implicit line joining
"Do it this way.\n")
No: print """This is pretty ugly. Don't do this. """
10. Closing files and sockets
Explicitly close files and sockets when done with them.
The preferred way to manage files is using the "with" statement:
with open("hello.txt") as hello_file: for line in hello_file: print line
For file-like objects that do not support the "with" statement, use contextlib.closing():
import contextlib with contextlib.closing(urllib.urlopen("http://www.python.org/")) as front_page: for line in front_page: print line
11. TODO comments
Use
TODO
comments for code that is temporary, a short-term solution, or good-enough but not perfect.example:
# TODO(kl@gmail.com): Use a "*" here for string repetition. # TODO(Zeke) Change this to use relations.
12. Import
Imports should be on separate lines.
E.g.:
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:
Yes: import os import sys
No: import os, sys
- standard library imports
- third-party imports
- application-specific imports
import foo from foo import bar from foo.bar import baz from foo.bar import Quux from Foob import ar
13. One statements per Line UNLESS Trivial
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
andexcept
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: bar(foo)
No:
if foo: bar(foo)
else: baz(foo)
try: bar(foo)
except ValueError: baz(foo)
try:
bar(foo)
except ValueError: baz(foo)
14. Setter in the OOP
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.
Reason behind: it is Python (interpreted) not Java (Compiled)
15. Main()
Even a file meant to be used as a script should be importable and a mere import should not have the side effect of executing the script's main functionality. The main functionality should be in a main() function.
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.def main(): ... if __name__ == '__main__': 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.done
No comments:
Post a Comment