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.
Standards are listed under the chapter where they first become applicable.
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)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.
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.
Use white space to make code clearer:
+ and =
z=3*x+5.2*yz = 3 * x + 5.2 * yIdentifiers (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.
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.)
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
#234567890123456789012345678901234567890123456789012345678901234567890123456789Avoid 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"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.
Use boolean variables and expressions outside the context of an if statement to simplify code. For example,
return x == yis preferable to
if x == y
return True
else
return FalseUsually, True and False should be used in boolean context rather than 1 and 0 or other values.
Use comments to identify and briefly describe each problem, e.g.,
# Page 205, Exercise 6.10
# Display an animated, dancing skeletonSpace after the # in all comments. Like this:
# This is a good comment.Not like this:
#This is a bad comment.(Effective Oct. 23, 2015)
Correct spelling in comments and code makes the program easier to read and understand.
Code should be clear, simple, and straightforward to the extent possible. Avoid obscure and bizarre usages and unnecessary complexity.
Code that is not self-explanatory should be documented with comments.
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.
Use parentheses if they will help to clarify complex expressions.
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.
Use functions to avoid code repetition. It is hard to give strict rules about this, but here are some rules of thumb:
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.
No additional standards.
Variables that are used only by one method should be declared as local variables, within the method, rather than instance variables.
Avoid using the same name for a local variable and an instance variable (shadowing).
Use meaningful and appropriate method names, just as you would use meaningful and appropriate variable names.
Use blank lines to separate methods.
In general, rules for style concerning functions apply also to methods.
Use character-case to distinguish between the names of classes, functions, variables, and constants:
Use “CamelCase” for class names: begin with a capital letter, and capitalize “word parts” within the name.
Examples: Point, GeometricObject, SolarSystem
Begin variable and function names (this applies also to instance variables and and methods) with a lower-case letter. Either separate “word parts” with underscores, or capitalize following “word parts”; but do it the same way consistently within a program.
bear, bear_facts, live_a_littlebear, bearFacts, liveALittleUse all-upper-case identifiers for constants. Separate word parts with underscores.
PI, FISH_SHAPEModule names should be all lower-case, with word parts separated by underscores.
Examples: point, geometric_object, solar_system
Design of class hierarchies:
Use abstract classes to specify behaviors that are required but not (yet) defined.
Avoid shadowing inherited instance variables. Shadowing occurs when a subclass and superclass have instance variables with the same name.
Let each class manage its own data, using constructors, accessors, and mutators.
Use other object-oriented design techniques (in addition to inheritance) to avoid redundancy:
# rule.