Coding Standards for Python Programs

Version 5.1.41

This document gives some rules of thumb for writing programs in good style. No set of rules can cover all possible situations; use common sense always. The purpose of good style is to make programs easily readable and intelligible. This has at least two important benefits: it helps us avoid errors when writing the program initially, and we or others who subsequently need to revise the program won’t be confused.

How to Develop Programs

Coding Standards

Standards are listed under the chapter where they first become applicable.

Chapter 1: Introduction

  1. Begin each source file with a header comment which shows the course number, lab number, author’s name(s), and date, in this form:

    # INFO I210, Lab (Number)
    # (Your name(s))
    # (Today's date)
  2. Put all import statements near the top of the file, just below the header comment (but separated from it by a blank line), before any function definitions or other code.

  3. Write a docstring for the main function in each problem. The docstring comes just below the function header (the line that begins def) and is enclosed in triple quotation marks (''' ... ''' or """ ... """). The docstring should give a summary of the function; then describe the function’s arguments; and then describe the result of the function, which is either the function’s return value, or the action or side-effect which it performs.

    Examples:

    def add1(k):
        """Add 1 to a number.
        Argument: k is a number.
        Returns: k + 1."""
        return k + 1
    
    def happy(phrase, n):
        """Print a happy phrase repeatedly.
        Arguments: phrase is a string, n is a number.
        Action: Print 'Happy <phrase>', repeated <n> times."""
        for i in range(n):
            print("Happy " + phrase)

    Note that the docstring can, and usually should, span multiple lines, instead of being one long line (see rule 7).

    Docstrings for helping functions not specifically required by the lab instructions are optional.

  4. Use white space to make code clearer:

  5. Identifiers (such as variable, function, and module names) should be meaningful and (even more importantly) not misleading. This applies to function parameters as well as other variables.

    Good:

    student_name = "Jack"

    Bad, meaningless:

    n = "Jack"

    Even worse, misleading:

    score = "Jack"

    However, in some contexts it is okay to use short, standard variable names, like i and j for indexes or counters in a loop, and n for a generic integer (in a purely mathematical function).

    For long identifiers, use underscores or capitalization to separate the parts, e.g., best_of_three or bestOfThree.

  6. Where Python requires code to be indented (function bodies, for statements, etc.), use four spaces for each level of indentation. Do not use TAB characters to indent. (But you may use the Tab key if your editor converts it to spaces. Good editors allow you to configure the Tab key to do this.)

  7. Lines should never be more than 79 characters wide, and it is best if they are no more than 72 characters wide. Longer lines will “wrap around” when printed, or when viewed in your grader’s text editor, making them ugly and hard to read. Split complex statements across lines at sensible breaking points, and indent the remaining lines until the end of the statement. In some cases, you may need to put \ at the end of a line, telling Python you are going to continue the statement on the next line.

    Example:

    # Bad (line is 87 characters):
    
        return reduce(plus, map(first_letter, filter(compose(neg, is_article), words)))
    
    
    # Better:
        return reduce(plus,
                      map(first_letter,
                          filter(compose(neg, is_article),
                                 words)))
    
    # Alternatively:
        return reduce(plus, \
                      map(first_letter, \
                          filter(compose(neg, is_article), \
                                 words)))
    

    Hint: it is a good idea to not maximize your text editor window, or to make it any wider than it is when it starts up. A wide window will tempt you to write lines that are too long.

    If you’re in doubt about the width of your editor window, you can copy and paste in these lines to check:

#        1         2         3         4         5         6         7
#234567890123456789012345678901234567890123456789012345678901234567890123456789

Chapter 2: Pi-thon

  1. Avoid redundant tests in if statements. For example,

    if score > 85:
      return "Good"
    elif score > 50:
      return "So-so"
    else:
      return "Poor"

    is preferable to

    if score > 85:
      return "Good"
    elif score > 50 and score <= 85:
      return "So-so"
    elif score <= 50:
      return "Poor"
  2. If an if statement has one or more elif clauses, it should end with an else clause to make it sure and clear that all cases have been covered. The else clause might print an error message for an unexpected value.

  3. Use boolean variables and expressions outside the context of an if statement to simplify code. For example,

    return x == y

    is preferable to

    if x == y
      return True
    else
      return False
  4. Usually, True and False should be used in boolean context rather than 1 and 0 or other values.

Chapter 3: Codes and Other Secrets

  1. Use comments to identify and briefly describe each problem, e.g.,

    # Page 205, Exercise 6.10
    # Display an animated, dancing skeleton
  2. Space after the # in all comments. Like this:

    # This is a good comment.

    Not like this:

    #This is a bad comment.

    (Effective Oct. 23, 2015)

  3. Correct spelling in comments and code makes the program easier to read and understand.

  4. Code should be clear, simple, and straightforward to the extent possible. Avoid obscure and bizarre usages and unnecessary complexity.

  5. Code that is not self-explanatory should be documented with comments.

  6. Use spaces to separate the parts of expressions and lists. For example (I am using to represent a space more visibly), 5␣*␣(x␣+␣1) is better than 5*(x+1).

    But, do not use spaces to separate parentheses from what they contain. Write (x␣+␣1), not (␣x␣+␣1␣). Likewise, do not space between a list, string, dictionary, or tuple and its subscript. For example, write scholar[i], not scholar␣[i]. Spacing is not required around the : in a slice operation: myString[2:8] is fine.

  7. Use parentheses if they will help to clarify complex expressions.

  8. If a function is getting too complex, divide it into subproblems, and define a helping function for each of the subproblems. Generally, several short functions are better than a single long function.

  9. Use functions to avoid code repetition. It is hard to give strict rules about this, but here are some rules of thumb:

    1. One complex line repeated two or more times.
    2. Two or more simple lines repeated two or more times.
  10. Use functions to improve code clarity. Sometimes the meaning of a few lines of code, or even one line, can be made clearer by wrapping it in a function definition and giving it a name. This may be true even if the lines are unrepeated.

Chapters 4–9

No additional standards.

Chapter 10: Writing Classes

  1. Variables that are used only by one method should be declared as local variables, within the method, rather than instance variables.

  2. Avoid using the same name for a local variable and an instance variable (shadowing).

  3. Use meaningful and appropriate method names, just as you would use meaningful and appropriate variable names.

  4. Use blank lines to separate methods.

  5. In general, rules for style concerning functions apply also to methods.

  6. Use character-case to distinguish between the names of classes, functions, variables, and constants:

Chapter 12: Inheritance

  1. Design of class hierarchies:

    1. Keep common features as high in the hierarchy as possible. This maximizes software re-use and minimizes the needs of software maintenance.
    2. Override or specialize methods to make exceptions to general rules.
    3. Only use subclasses when there is an “is-a” relationship.
    4. There is no one best class hierarchy for all purposes; think carefully about what design works best for the application.
  2. Use abstract classes to specify behaviors that are required but not (yet) defined.

  3. Avoid shadowing inherited instance variables. Shadowing occurs when a subclass and superclass have instance variables with the same name.

  4. Let each class manage its own data, using constructors, accessors, and mutators.

  5. Use other object-oriented design techniques (in addition to inheritance) to avoid redundancy:

    1. The “has a” relationship: an object can have instance variables that refer to other objects.
    2. Delegation: an object performs a task by asking another object to perform the task.
    3. Polymorphism: different classes can define methods with the same name that behave differently. For example, different shapes draw themselves in different ways.

Reference


  1. Version log:
    • 5.1.4, 2016 Oct 14. Explicitly state no additional standards for chs. 4–9.
    • 5.1.3, 2016 Sep 30. Clarify rule about long lines and how to continue a statement on multiple lines.
    • 5.1.2, 2015 Nov 14. Simplify headings for chapters 10 and 12.
    • 5.1.1, 2015 Oct 31. Added link for configuring the TAB key.
    • 5.1, 2015 Oct 23. Added space after # rule.
    • 5, 2015 Oct 3. Move file header comment requirement to ch. 1. Add docstring requirement. Add Python syntax highlighting. Use visible blank character for spacing examples.
    • 4, 2012 Sep 8. Converted from Restructured Text to Markdown. Moved some rules to chapters 1 and 2.
    • 3, 2011 Sep 18. Moved rules for chapter 5 to chapter 3.
    • 2, 2009 Nov 18. Added rules for object-oriented programs.
    • 1, 2009 Oct 3.