Tuesday, December 11, 2012

1 Python Language Rules

source: http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
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 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 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 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.
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


14 True/False evaluation
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. (Not robust as Java)


  • Singleton: Never use == or != to compare singletons like None. Use is or is not.
  • if x is not None: 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!
  • if not x, rather than if x == False: Never compare a boolean variable to 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:.
  • None vs. False
  • Sequence data type: 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):.(waste of computational resources)
  • Integer: When handling integers, implicit false may involve more risk than benefit (i.e., accidentally handling 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 ...
    
    
    is equivalent to:
    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