Drop the sections on pychecker, exceptions, global variables, nested/local/inner classes and functions, and list comprehensions as we do not differ from the Google Python Style Guide in those regards.
diff --git a/PythonStyleGuide.wiki b/PythonStyleGuide.wiki index 96d0443..2720891 100644 --- a/PythonStyleGuide.wiki +++ b/PythonStyleGuide.wiki
@@ -29,12 +29,7 @@ == Python Language Rules == - # [PythonStyleGuide#pychecker pychecker]: _Recommended_ # [PythonStyleGuide#Imports Imports]: _Import only modules and only by name *(no wildcard imports)*_ - # [PythonStyleGuide#Exceptions Exceptions]: _Yes_ - # [PythonStyleGuide#Global_variables Global variables]: _Use sparingly_ - # [PythonStyleGuide#Nested_Local_Inner_Classes_and_Functions Nested/Local/Inner Classes and Functions]: _Yes_ - # [PythonStyleGuide#List_Comprehensions List Comprehensions]: _Yes, *if simple*_ # [PythonStyleGuide#Default_Iterators_and_Operators Default Iterators and Operators]: _Yes_ # [PythonStyleGuide#Generators Generators]: _Yes_ # [PythonStyleGuide#Using_apply_filter_map_reduce Using apply, filter, map, reduce]: _Yes, *for one-liners*_ @@ -79,51 +74,6 @@ = Python Language Rules = -== pychecker == - -*What it is:* `pychecker` is a tool for finding bugs in Python source code. -It finds problems that are typically caught by a compiler for less dynamic -languages like C and C++. It is similar to lint. Because of the dynamic -nature of Python, some warnings may be incorrect; however, spurious -warnings should be fairly infrequent. - -*Pros:* Catches easy-to-miss errors like typos, use-vars-before-assignment, etc. - -*Cons:* `pychecker` isn't perfect. To take advantage of it, we'll need to -sometimes: a) Write around it b) Suppress its warnings c) Improve it or -d) Ignore it. - -*Decision:* Make sure you run `pychecker` on your code. - -To suppress warnings, you can set a module-level variable named -`__pychecker__` to suppress appropriate warnings. For example: - -{{{ -__pychecker__ = 'no-callinit no-classattr' -}}} - -Suppressing in this way has the advantage that we can easily search for -suppressions and revisit them. - -You can get a list of `pychecker` warnings by doing `pychecker --help`. - -Unused argument warnings can be suppressed by using `_` as the identifier -for the unused argument or prefixing the argument name with `unused_`. -In situations where changing the argument name is infeasible, you can -mention them at the begining of the function. For example: - -{{{ -def Foo(a, unused_b, unused_c, d=None, e=None): - d, e = (d, e) # silence pychecker - return a -}}} - -Ideally, `pychecker` would be extended to ensure that such -'unused declarations' were true. - -You can find more information on the -[http://www.google.com/url?sa=D&q=http://pychecker.sourceforge.net PyChecker homepage]. - == Imports == *What it is:* Mechanism for making use of code between modules. @@ -155,116 +105,6 @@ without the full package name. This might cause the package to be imported twice and have unintended side effects. -== Exceptions == - -*What they are:* Exceptions are a means of breaking out of the normal flow -of control of a code block to handle errors or other exceptional conditions. - -*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. - -*Decision:* Exceptions are very Pythonic so we allow them, too, but only -as long as certain conditions are met: - - * 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 `Error`. - -{{{ -class Error(Exception): - """Base exception for all exceptions raised in module Foo.""" - pass -}}} - - * 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 Python syntax errors. It is easy to hide real bugs using `except:`. - * 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. - -== Global variables == - -*What it is:* Variables that are declared at the module level. - -*Pros:* Occasionally useful. - -*Cons:* Has the potential to change module behavior during the import, -because assignments to module-level variables are done when the module is -imported. - -*Decision:* 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 [PythonStyleGuide#Naming Naming] below. - * It is sometimes useful for globals to cache values needed or returned by functions. - * If needed, globals should be made internal to the module and accessed through public module level functions; see [PythonStyleGuide#Naming Naming] below. - -== Nested Local Inner Classes and Functions == - -*What they are:* A class can be defined inside of a function or class. A -function can be defined inside a function. Nested functions have read-only -access to variables defined in enclosing scopes. - -*Pros:* Allows definition of utility classes and functions that are only -used inside of a very limited scope. Very ADT-y. - -*Cons:* Instances of nested or local classes cannot be pickled. - -*Decision:* They are fine. - -== List Comprehensions == - -*What they are:* 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:* OK to use for one-liners, or when the `x for y in z` fits on one -line and a conditional on another (but see the example with the very-long -`x` below, which is a three-line case that is acceptable). Use loops -instead when things get more complicated. This is a judgment call. - -*No:* - -{{{ -# too complicated, use nested for loops instead -result = [(x, y) for x in range(10) - for y in range(5) - if x * y > 10] -}}} - -*Yes:* - -{{{ -# this case is complicated enough *not* to use a list comprehension -result = [] -for x in range(10): - for y in range(5): - if x * y > 10: - result.append((x, y)) - -# a nice, simple one-liner -squares = [x * x for x in range(10)] - -# a two-line generator (not list comprehension) case that is also OK -Eat(jelly_bean for jelly_bean in jelly_beans - if jelly_bean.color == 'black') - -# three-line case that is still debatably more readable than the equivalent loop -result = [someReallyLongWayToEatAJellyBean(jelly_bean) - for jelly_bean in jelly_beans - if jelly_bean != 'black'] -}}} - == Default Iterators and Operators == *What they are:* Container types, like dictionaries and lists, define