module_name,
package_name,
ClassName,
method_name,
ExceptionName,
function_name,
GLOBAL_CONSTANT_NAME,
global_var_name,
instance_var_name,
function_parameter_name,
local_var_name.
1. Pychecker
Linux
2. Imports
Use
import x
for importing packages and modules. Use
from x import y
where x
is the package prefix and y
is the module name with no prefix. Use
from x import y as z
if two modules named y
(same name) are to be imported or if y
is an inconveniently long name.
from sound.effects import echo ... echo.EchoFilter(input, output, delay=0.7, atten=4)
Do not use relative names in imports. Even if the module is in the same package, use the full package name. This helps prevent unintentionally importing a package twice.
3. package
All new code should import each module by its full package name.
Imports should be as follows:
# Reference in code with complete name. import sound.effects.echo # Reference in code with just module name (preferred). from sound.effects import echo
4. Exceptions
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.
- Never use catch-all
except:
statements, or catchException
orStandardError
, 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 andexcept:
will really catch everything including misspelled names, sys.exit() calls, Ctrl+C interrupts, unittest failures and all kinds of other exceptions that you simply don't want to catch. - Minimize the amount of code in a
try
/except
block. The larger the body of thetry
, 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, thetry
/except
block hides a real error. - Use the
finally
clause to execute code whether or not an exception is raised in thetry
block. This is often useful for cleanup, i.e., closing a file.
5. Avoid Global
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 Naming below.
6. Nested/Local/Inner Classes and Functions
A class can be defined inside of a method, function, or class. A function can be defined inside a method or function. Nested functions have read-only access to variables defined in enclosing scopes.
Decision: They are fine.
7. List Comprehension
Definition: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:
Okay to use for simple cases. Each portion must fit on one line: mapping expression,
for
clause, filter expression. Multiple for
clauses or filter expressions are not permitted. Use loops instead when things get more complicated.Yes: result = [] for x in range(10): for y in range(5): if x * y > 10: result.append((x, y)) for x in xrange(5): for y in xrange(5): if x != y: for z in xrange(5): if y != z: yield (x, y, z) return ((x, complicated_transform(x)) for x in long_generator_function(parameter) if x is not None) squares = [x * x for x in range(10)] 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]
8. List and Dictionary iterator
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.
9. Generator functions (to be continued)
Fine. Use "Yields:" rather than "Returns:" in the doc string for generator functions.
10. Lambda functions
Okay to use them for one-liners. If the code inside the lambda function is any longer than 60–80 chars, it's probably better to define it as a regular (nested) function.
For common operations like multiplication, use the functions from the
operator
module instead of lambda functions. For example, prefer operator.mul
to lambda x, y: x * y
. (it is reasonable to use already available modules or packages)
11. Conditional Expression
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
.
12. Default Argument value
Okay in most cases.
Avoid using mutable object as the default argument value, since default arguments are evaluated ONCE at module load time
Definition: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 provide 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:Okay 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 arguments with a default value. 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)
13. Properties
Use properties for accessing or setting data where you would normally have used simple, lightweight accessor or setter methods.
Definition: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. This also allows accessor methods to be added in the future without breaking the interface.
import math class Square(object): """A square with two properties: a writable area and a read-only perimeter. To use: >>> sq = Square(3) >>> sq.area //automatically we have area as property 9 >>> sq.perimeter //automatically we have perimeter as property 12 >>> sq.area = 16 >>> sq.side 4 >>> sq.perimeter 16 """ def __init__(self, side): self.side = side def __get_area(self): """Calculates the 'area' property.""" return self.side ** 2 def ___get_area(self): """Indirect accessor for 'area' property.""" return self.__get_area() def __set_area(self, area): """Sets the 'area' property.""" self.side = math.sqrt(area) def ___set_area(self, area): """Indirect setter for 'area' property.""" self.__set_area(area) area = property(___get_area, ___set_area, doc="""Gets or sets the area of the square.""") @property def perimeter(self): return self.side * 4
Definition:Python evaluates certain values as
Singleton: Never use
if x is not None: Beware of writing
if not x, rather than if x == False: Never compare a boolean variable to
None vs. False
Sequence data type: For sequences (strings, lists, tuples), use the fact that empty sequences are false, so
Integer: When handling integers, implicit false may involve more risk than benefit (i.e., accidentally handling
Note that
15. Deprecated Language Feature
Use string methods instead of the
Use new features, use method rather than module functions.
others map\apply\list comprehension, to be continued when have enough advanced Python knowledge.
16. Lexical Scoping
LEG-B rule
Function inside the function: 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.
OK to use; but be careful with namespace of composite datatype
17. Function and Method Decorator
is equivalent to:
18. Power Feature
done.
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. (Not robust as Java)==
or !=
to compare singletons like None
. Use is
or is not
.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!False
using ==
. Use if not x:
instead. If you need to distinguish False
from None
then chain the expressions, such as if not x and x is not None:
.if not seq:
or if seq:
is preferable to if len(seq):
or if not len(seq):
.(waste of computational resources)None
as 0). You may compare a value which is known to be an integer (and is not the result of len()
) against the integer 0.Note that
'0'
(i.e., 0
as string) evaluates to true
Yes: if not users: print 'no users' if foo == 0: self.handle_zero() if i % 10 == 0: self.handle_multiple_of_ten()
No: if len(users) == 0: print 'no users' if foo is not None and not foo: self.handle_zero() if not i % 10: self.handle_multiple_of_ten()
15. Deprecated Language Feature
Use string methods instead of the
string
module where possible. Use function call syntax instead of apply
. Use list comprehensions and for
loops instead of filter
and map
when the function argument would have been an inlined lambda anyway. Use for
loops instead of reduce
.
Use new features, use method rather than module functions.
others map\apply\list comprehension, to be continued when have enough advanced Python knowledge.
Yes: words = foo.split(':') [x[1] for x in my_list if x[2] == 5] map(math.sqrt, data) # Ok. No inlined lambda expression. 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)
16. Lexical Scoping
LEG-B rule
Function inside the function: 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.
OK to use; but be careful with namespace of composite datatype
17. Function and Method Decorator
Definition:Decorators for Functions and Methods (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 my_decorator
, this:class C(object): @my_decorator def method(self): # method body ...
class C(object): def method(self): # method body ... method = my_decorator(method)
Method As Object. Function name and namespace
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 pydoc 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 main for more discussion.
18. Power Feature
Definition: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 your code.
done.
No comments:
Post a Comment