From 424ad34281beb67dcb5cd9294d638d564169d061 Mon Sep 17 00:00:00 2001
From: "apicard@google.com"
Date: Tue, 18 Sep 2012 23:16:02 +0000
Subject: [PATCH] Updating python style guide
---
pyguide.html | 298 ++++++++++++++++++++++++++++++++++-----------------
1 file changed, 202 insertions(+), 96 deletions(-)
diff --git a/pyguide.html b/pyguide.html
index af00822..30357f3 100644
--- a/pyguide.html
+++ b/pyguide.html
@@ -136,7 +136,7 @@
Google Python Style Guide
- Revision 2.29
+ Revision 2.39
@@ -165,12 +165,12 @@
|
|
+pychecker Imports Packages Exceptions Global variables Nested/Local/Inner Classes and Functions List Comprehensions Default Iterators and Operators Generators Lambda Functions Conditional Expressions Default Argument Values Properties True/False evaluations Deprecated Language Features Lexical Scoping Function and Method Decorators Threading Power Features
|
|
+Semicolons Line length Parentheses Indentation Blank Lines Whitespace Shebang Line Comments Classes Strings Files and Sockets TODO Comments Imports formatting Statements Access Control Naming Main
@@ -223,7 +223,7 @@
Run pychecker
over your code.
-
+
Definition:
PyChecker is a tool for finding bugs in Python source code. It finds
@@ -243,7 +243,7 @@
Suppress its warnings c) Improve it or d) Ignore it.
-Decision:
+Decision:
Make sure you run pychecker
on your code.
@@ -254,7 +254,7 @@
To suppress warnings, you can set a module-level variable named
- __pychecker__
to suppress appropriate warnings.
+ __pychecker__
to suppress appropriate warnings.
For example:
@@ -264,7 +264,7 @@
for suppressions and revisit them.
- You can get a list of pychecker warnings by doing
+ You can get a list of pychecker warnings by doing
pychecker --help
.
@@ -276,7 +276,7 @@
def foo(a, unused_b, unused_c, d=None, e=None):
- (d, e) = (d, e) # Silence pychecker
+ _ = d, e
return a
@@ -406,11 +406,11 @@ from sound.effects import echo
Exceptions must follow certain conditions:
- - 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"
).
+ - 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
@@ -436,6 +436,14 @@ from sound.effects import echo
- 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.
+ - When capturing an exception, use
as
rather than
+ a comma. For example:
+
+try:
+ raise Error
+except Error as error:
+ pass
+
@@ -547,15 +555,6 @@ from sound.effects import echo
permitted. Use loops instead when things get more complicated.
-
No:
- result = [(x, y) for x in range(10) for y in range(5) if x * y > 10]
-
- return ((x, y, z)
- for x in xrange(5)
- for y in xrange(5)
- if x != y
- for z in xrange(5)
- if y != z)
Yes:
result = []
for x in range(10):
@@ -578,6 +577,15 @@ from sound.effects import echo
eat(jelly_bean for jelly_bean in jelly_beans
if jelly_bean.color == 'black')
+
No:
+ result = [(x, y) for x in range(10) for y in range(5) if x * y > 10]
+
+ return ((x, y, z)
+ for x in xrange(5)
+ for y in xrange(5)
+ if x != y
+ for z in xrange(5)
+ if y != z)
@@ -586,7 +594,7 @@ from sound.effects import echo
link
▶
- Use default iterators and operators for types that support them,
+ Use default iterators and operators for types that support them,
like lists, dictionaries, and files.
@@ -648,7 +656,7 @@ from sound.effects import echo
function that creates an entire list of values at once.
-Cons:
+Cons:
None.
@@ -699,6 +707,37 @@ from sound.effects import echo
+
+
+ link
+ ▶
+
+ Okay for one-liners.
+
+
+
+Definition:
+ Conditional expressions are mechanisms that provide a shorter syntax
+ for if statements. For example:
+ x = 1 if cond else 2
.
+
+
+Pros:
+ Shorter and more convenient than an if statement.
+
+
+Cons:
+ May be harder to read than an if statement. The condition may be difficult
+ to locate if the expression is long.
+
+
+Decision:
+ Okay to use for one-liners. In other cases prefer to use a complete if
+ statement.
+
+
+
+
link
@@ -726,7 +765,7 @@ from sound.effects import echo
"faking" the overloading behavior.
-Cons:
+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
@@ -765,8 +804,8 @@ from sound.effects import echo
link
▶
- Use properties for accessing or setting data where you would
- normally have used simple, lightweight accessor or setter methods.
+ Use properties for accessing or setting data where you would
+ normally have used simple, lightweight accessor or setter methods.
@@ -797,7 +836,7 @@ from sound.effects import echo
Decision: Use properties in new code to access or
set data where you would normally have used simple, lightweight
accessor or setter methods. Read-only properties should be created
- with the @property
+ with the @property
decorator.
@@ -868,7 +907,7 @@ from sound.effects import echo
Definition: 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.
+ '' all evaluate as false
in a boolean context.
Pros: Conditions using Python booleans are easier to read
@@ -963,16 +1002,16 @@ from sound.effects import echo
We do not use any Python version which does not support
these features, so there is no reason not to use the new
styles.
-
No: words = string.split(foo, ':')
-
- map(lambda x: x[1], filter(lambda x: x[2] == 5, my_list))
-
- apply(fn, args, kwargs)
Yes: words = foo.split(':')
[x[1] for x in my_list if x[2] == 5]
fn(*args, **kwargs)
+
No: words = string.split(foo, ':')
+
+ map(lambda x: x[1], filter(lambda x: x[2] == 5, my_list))
+
+ apply(fn, args, kwargs)
@@ -995,7 +1034,7 @@ from sound.effects import echo
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:
@@ -1018,7 +1057,7 @@ from sound.effects import echo
Cons:
- Can lead to confusing bugs. Such as this example based on
+ Can lead to confusing bugs. Such as this example based on
PEP-0227:
i = 4
@@ -1034,7 +1073,7 @@ from sound.effects import echo
So foo([1, 2, 3])
will print 1 2 3 3
, not
1 2 3 4
.
-
+
Decision:
@@ -1132,7 +1171,7 @@ from sound.effects import echo
- Use the Queue module's Queue
data type as the preferred
+ Use the Queue module's Queue
data type as the preferred
way to
communicate data between threads. Otherwise, use the threading
module and its locking primitives. Learn about the proper use
@@ -1171,7 +1210,7 @@ from sound.effects import echo
difficult than code that is longer but is straightforward.
-Decision:
+Decision:
Avoid these features in
your code.
@@ -1202,8 +1241,8 @@ from sound.effects import echo
- Exception: lines importing modules may end up longer than 80
- characters only if using Python 2.4 or
+ Exception: lines importing modules may end up longer than 80
+ characters only if using Python 2.4 or
earlier.
@@ -1239,7 +1278,7 @@ from sound.effects import echo
Make note of the indentation of the elements in the line
- continuation examples above; see the
+ continuation examples above; see the
indentation
section for explanation.
@@ -1255,8 +1294,8 @@ from sound.effects import echo
- Do not use them in return statements or conditional statements unless
- using parentheses for implied line continuation. (See above.)
+ 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.
@@ -1320,7 +1359,7 @@ from sound.effects import echo
link
▶
- Two blank lines between top-level definitions, one blank line
+ Two blank lines between top-level definitions, one blank line
between method definitions.
@@ -1339,7 +1378,7 @@ from sound.effects import echo
link
▶
- Follow standard typographic rules for the use of spaces around
+ Follow standard typographic rules for the use of spaces around
punctuation.
@@ -1395,16 +1434,16 @@ from sound.effects import echo
long_name = 2 # comment that should not be aligned
dictionary = {
- "foo": 1,
- "long_name": 2,
+ 'foo': 1,
+ 'long_name': 2,
}
No:
foo = 1000 # comment
long_name = 2 # comment that should not be aligned
dictionary = {
- "foo" : 1,
- "long_name": 2,
+ 'foo' : 1,
+ 'long_name': 2,
}
@@ -1469,15 +1508,9 @@ from sound.effects import echo
- Every file should contain the following items, in order:
-
- - a copyright statement (for example,
-
Copyright 2008 Google Inc.
)
- - a license boilerplate. Choose the appropriate boilerplate
- for the license used by the project (for example, Apache 2.0, BSD,
- LGPL, GPL)
- - an author line to identify the original author of the file
-
+ 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)
@@ -1616,9 +1649,9 @@ from sound.effects import echo
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
+ 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.
@@ -1663,17 +1696,6 @@ from sound.effects import echo
from
object
. This also applies to nested classes.
-
No: class SampleClass:
- pass
-
-
- class OuterClass:
-
- class InnerClass:
- pass
-
-
-
Yes: class SampleClass(object):
pass
@@ -1688,9 +1710,18 @@ from sound.effects import echo
"""Explicitly inherits from another class already."""
+
No: class SampleClass:
+ pass
+
+ class OuterClass:
+
+ class InnerClass:
+ pass
+
+
Inheriting from object
is needed to make properties work
- properly, and it will protect your code from one particular potential
+ properly, and it will protect your code from one particular potential
incompatibility with Python 3000. It also defines
special methods that implement the default semantics of objects including
__new__
, __init__
, __delattr__
,
@@ -1710,12 +1741,13 @@ from sound.effects import echo
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)
+
No: x = '%s%s' % (a, b) # use + in this case
+ x = imperative + ', ' + expletive + '!'
+ x = 'name: ' + name + '; score: ' + str(n)
Avoid using the +
and +=
operators to
@@ -1726,15 +1758,15 @@ from sound.effects import echo
substring to a cStringIO.StringIO
buffer).
-
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)
+
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>'
Use """
for multi-line strings rather than
@@ -1743,14 +1775,88 @@ from sound.effects import echo
not flow with the indentation of the rest of the program:
-
No:
+Yes:
+ print ("This is much nicer.\n"
+ "Do it this way.\n")
+ No:
print """This is pretty ugly.
Don't do this.
"""
-Yes:
- print ("This is much nicer.\n"
- "Do it this way.\n")
+
+
+
+
+
+
+ link
+ ▶
+
+ Explicitly close files and sockets when done with them.
+
+
+
+ Leaving files, sockets or other file-like objects open unnecessarily
+ has many downsides, including:
+
+
+ - They may consume limited system resources, such as file
+ descriptors. Code that deals with many such objects may exhaust
+ those resources unnecessarily if they're not returned to the
+ system promptly after use.
+ - Holding files open may prevent other actions being performed on
+ them, such as moves or deletion.
+ - Files and sockets that are shared throughout a program may
+ inadvertantly be read from or written to after logically being
+ closed. If they are actually closed, attempts to read or write
+ from them will throw exceptions, making the problem known
+ sooner.
+
+
+
+
+ Furthermore, while files and sockets are automatically closed when the
+ file object is destructed, tying the life-time of the file object to
+ the state of the file is poor practice, for several reasons:
+
+
+ - There are no guarantees as to when the runtime will actually run
+ the file's destructor. Different Python implementations use
+ different memory management techniques, such as delayed Garbage
+ Collection, which may increase the object's lifetime arbitrarily
+ and indefinitely.
+ - Unexpected references to the file may keep it around longer than
+ intended (e.g. in tracebacks of exceptions, inside globals,
+ etc).
+
+
+
+
+ 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
+
+
+ Legacy AppEngine code using Python 2.5 may enable the "with" statement
+ using "from __future__ import with_statement".
+
@@ -1880,8 +1986,8 @@ Don'
t do this.
▶
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
+ 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.
@@ -1916,7 +2022,7 @@ Don'
t do this.
single character names except for counters or iterators
dashes (-
) in any package/module name
-__double_leading_and_trailing_underscore__
names
+__double_leading_and_trailing_underscore__
names
(reserved by Python)
@@ -1936,14 +2042,14 @@ Don'
t do this.
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
+ 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.
Use CapWords for class names, but lower_with_under.py for module names.
Although there are many existing modules named CapWords.py, this is now
- discouraged because it's confusing when the module happens to be
- named after a class. ("wait -- did I write
+ discouraged because it's confusing when the module happens to be
+ named after a class. ("wait -- did I write
import StringIO
or from StringIO import
StringIO
?")
@@ -2045,9 +2151,9 @@ Don'
t do this.
link
▶
- 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()
+ 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.
@@ -2057,7 +2163,7 @@ Don'
t do this.
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.
+ module is imported.
@@ -2112,7 +2218,7 @@ Don'
t do this.
-Revision 2.29
+Revision 2.39