CS 240: Data Structures and Algorithms
James Madison University, Fall 2014

CS240 Python Coding Conventions

For this course we will primarily follow the PEP 8 Style Guide for Python Code. This is the style guide that describes the coding standards for code to be included in the Python standard library. I encourage you to read that entire document, but you are only responsible for the boxed (and edited) excerpts included on this page. I also recommend taking a look at Google Python Style Guide. Again, you are not responsible for that material, but it has some good advice for writing well organized Python code.

Code lay-out

Executable programs for this course should define a main function that is called from within a conditional block like the following:

if __name__ == "__main__":
    main()
Under no circumstances should your modules include function calls that occur unconditionally. Such calls interfere with the use of PyDoc, and make it difficult for me to use testing code that imports your module.

PEP 8:
Indentation
-----------

Use 4 spaces per indentation level.


Tabs or Spaces?
---------------

Spaces are the preferred indentation method.


Maximum Line Length
-------------------

Limit all lines to a maximum of 79 characters.

For flowing long blocks of text with fewer structural restrictions
(docstrings or comments), the line length should be limited to 72
characters.

Limiting the required editor window width makes it possible to have
several files open side-by-side, and works well when using code
review tools that present the two versions in adjacent columns.

The default wrapping in most tools disrupts the visual structure of the
code, making it more difficult to understand. The limits are chosen to
avoid wrapping in editors with the window width set to 80, even
if the tool places a marker glyph in the final column when wrapping
lines. Some web based tools may not offer dynamic line wrapping at all.

The preferred way of wrapping long lines is by using Python's implied
line continuation inside parentheses, brackets and braces.  Long lines
can be broken over multiple lines by wrapping expressions in
parentheses. These should be used in preference to using a backslash
for line continuation.

Make sure to indent the continued line appropriately.  The preferred
place to break around a binary operator is *after* the operator, not
before it.  Some examples:

    class Rectangle(Blob):

        def __init__(self, width, height,
                     color='black', emphasis=None, highlight=0):
            if (width == 0 and height == 0 and
                    color == 'red' and emphasis == 'strong' or
                    highlight > 100):
                raise ValueError("sorry, you lose")
            if width == 0 and height == 0 and (color == 'red' or
                                               emphasis is None):
                raise ValueError("I don't think so -- values are %s, %s" %
                                 (width, height))
            Blob.__init__(self, width, height,
                          color, emphasis, highlight)


Blank Lines
-----------

Separate top-level function and class definitions with two blank
lines.

Method definitions inside a class are separated by a single blank
line.

Extra blank lines may be used (sparingly) to separate groups of
related functions.  Blank lines may be omitted between a bunch of
related one-liners (e.g. a set of dummy implementations).

Use blank lines in functions, sparingly, to indicate logical sections.

Imports

PEP 8:
- Imports should usually be on separate lines, e.g.:

      Yes: import os
           import sys

      No:  import sys, os

  It's okay to say this though:

      from subprocess import Popen, PIPE

- Imports are always put at the top of the file, just after any module
  comments and docstrings, and before module globals and constants.

- Wildcard imports (from <module> import *) should be avoided, as
  they make it unclear which names are present in the namespace,
  confusing both readers and many automated tools.

Whitespace in Expressions and Statements

PEP 8:
Avoid extraneous whitespace in the following situations:

- Immediately inside parentheses, brackets or braces. :

      Yes: spam(ham[1], {eggs: 2})
      No:  spam( ham[ 1 ], { eggs: 2 } )

- Immediately before a comma, semicolon, or colon:

      Yes: if x == 4: print x, y; x, y = y, x
      No:  if x == 4 : print x , y ; x , y = y , x

- Immediately before the open parenthesis that starts the argument
  list of a function call:

      Yes: spam(1)
      No:  spam (1)

- Immediately before the open parenthesis that starts an indexing or
  slicing:

      Yes: dict['key'] = list[index]
      No:  dict ['key'] = list [index]

- More than one space around an assignment (or other) operator to
  align it with another.

  Yes:

      x = 1
      y = 2
      long_variable = 3

  No:

      x             = 1
      y             = 2
      long_variable = 3


Other Recommendations
---------------------

- Always surround these binary operators with a single space on either
  side: assignment (=), augmented assignment (+=, -=
  etc.), comparisons (==, <, >, !=, <>, <=,
  >=, in, not in, is, is not), Booleans (and,
  or, not).

- Don't use spaces around the = sign when used to indicate a
  keyword argument or a default parameter value.

  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)

- Compound statements (multiple statements on the same line) are
  generally discouraged.

  Yes:

      if foo == 'blah':
          do_blah_thing()
      do_one()
      do_two()
      do_three()

  Rather not:

      if foo == 'blah': do_blah_thing()
      do_one(); do_two(); do_three()

Comments

The point of comments is to clarify code that might otherwise be difficult for the reader to follow. Well organized Python code with informative variable names should require very few comments inside the bodies of functions and methods.

PEP 8:
Comments that contradict the code are worse than no comments.  Always
make a priority of keeping the comments up-to-date when the code
changes!

Comments should be complete sentences.  If a comment is a phrase or
sentence, its first word should be capitalized, unless it is an
identifier that begins with a lower case letter (never alter the case
of identifiers!).

If a comment is short, the period at the end can be omitted.  Block
comments generally consist of one or more paragraphs built out of
complete sentences, and each sentence should end in a period.

You should use two spaces after a sentence-ending period.

When writing English, follow Strunk and White.


Block Comments
--------------

Block comments generally apply to some (or all) code that follows
them, and are indented to the same level as that code.  Each line of a
block comment starts with a # and a single space (unless it is
indented text inside the comment).

Paragraphs inside a block comment are separated by a line containing a
single #.

Inline Comments
---------------

Use inline comments sparingly.

An inline comment is a comment on the same line as a statement.
Inline comments should be separated by at least two spaces from the
statement.  They should start with a # and a single space.

Inline comments are unnecessary and in fact distracting if they state
the obvious.  Don't do this:

    x = x + 1                 # Increment x

But sometimes, this is useful:

    x = x + 1                 # Compensate for border

Documentation Strings

PEP 8:
Conventions for writing good documentation strings
(a.k.a. "docstrings") are immortalized in PEP 257.

- Write docstrings for all public modules, functions, classes, and
  methods.  Docstrings are not necessary for non-public methods, but
  you should have a comment that describes what the method does.  This
  comment should appear after the def line.

- PEP 257 describes good docstring conventions.  Note that most
  importantly, the """ that ends a multiline docstring should be
  on a line by itself, e.g.:

      """Return a foobang

      Optional plotz says to frobnicate the bizbaz first.
      """

- For one liner docstrings, please keep the closing """ on
  the same line.

Module headers should include a brief description of the module as well as author and version information. A separate block comment should include your honor code statement.

Naming Conventions

Selecting informative names is one of the most important steps in writing readable, maintainable, and correct code. Variable names should generally be nouns, and should clearly describe what the variable is intended to contain. Single letter variable are almost never acceptable, with exception of loop index variables. It is usually a good idea to use plural nouns for variables that will contain collections, and singular nouns for variables that will contain individual objects.

Variable names should balance clarity with brevity. The name person is better than current_person_object. However, per is worse than either (percentage? person?, permitted?).

Function and method names should typically be verbs and should describe what the function or method is intended to accomplish.

Avoid selecting place-holder names with the intention of replacing them later. If you aren't sure what the variable or function should be named, that's often an indication that you don't have a clear idea of what the variable will hold or what the function should accomplish. Taking the time to figure out an appropriate name will clarify your thinking.

PEP 8

Names to Avoid
~~~~~~~~~~~~~~

Never use the characters 'l' (lowercase letter el), 'O' (uppercase
letter oh), or 'I' (uppercase letter eye) as single character variable
names.

In some fonts, these characters are indistinguishable from the
numerals one and zero.  When tempted to use 'l', use 'L' instead.

Module Names
~~~~~~~~~~~~~~~~~~~~~~~~

Modules should have short, all-lowercase names.  Underscores can be
used in the module name if it improves readability.  

Class Names
~~~~~~~~~~~

Class names should normally use the CapWords convention.


Exception Names
~~~~~~~~~~~~~~~

Because exceptions should be classes, the class naming convention
applies here.  However, you should use the suffix "Error" on your
exception names (if the exception actually is an error).


Function Names
~~~~~~~~~~~~~~

Function names should be lowercase, with words separated by
underscores as necessary to improve readability.


Method Names and Instance Variables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Use the function naming rules: lowercase with words separated by
underscores as necessary to improve readability.

Use one leading underscore only for non-public methods and instance
variables.


Constants
~~~~~~~~~

Constants are usually defined on a module level and written in all
capital letters with underscores separating words.  Examples include
MAX_OVERFLOW and TOTAL.
   

Programming Recommendations

PEP 8:
  - Comparisons to singletons like None should always be done with
  is or is not, never the equality operators.

- Use is not operator rather than not ... is.  While both
  expressions are functionally identical, the former is more readable
  and preferred.
  
  Yes:
  
      if foo is not None:
      
  No:
  
      if not foo is None:

- Don't compare boolean values to True or False using ==. :

      Yes:   if greeting:
      No:    if greeting == True:
      Worse: if greeting is True: