Skip to content

Python Coding Style Guide

Zhang Cheng edited this page Jun 30, 2017 · 10 revisions

PEP8

This standard needs to be satisfied in order for your code to be merged into master branch (this standard is checked by flake8 with pep8-naming plugin)

PEP8 needs to be strictly followed, since it is the most comprehensive and widely accepted style for python community.

Here is some of the highlights from PEP8:

  • Naming:

    • Function (and method) names should be lowercase, with words separated by underscores: def function_name()
    • Local variable should be lowercase, with words separated by underscore: local_variable = 1
    • Constants are written in all capital letters with underscores separating words: EXAMPLE_CONSTANTS = "constant string"
    • Class names should normally use the CapWords convention: class ExampleClass
  • Comment:

    • Each line of a block comment starts with a # and a single space. (do not use """ or ''' for block comment, they are used for doc string)
    • Inline comments should be separated by at least two spaces from the statement. They should start with a # and a single space.
  • max line length should be 79 char.

Variable Naming

This standard needs to be satisfied in order for your code to be merged into master branch

Avoid single-letter naming when you can:

YES 👍:

for index, element in enumerate(my_list):
    pass

NO 👎:

for i, e in enumerate(l):
    pass

DO NOT use function or type name as variable name:

YES 👍:

def example(input_list):
    length = len(input_list)

NO 👎:

def example(list):  # list is a type name
    len = len(list)   # len is a function name

Specify your function input clearly:

YES 👍:

def sort(unsorted_list):
    pass
def enable_files(file_ids):
    pass

NO 👎:

def sort(l):
    pass
def enable_files(ids):
    pass

HTML naming standard

  • The id attribute should use lowercase with underscore.
  • The class attribute should use lowercase case with hyphen.

YES 👍:

<p id="example_id" class="example-class"/>

NO 👎:

<p id="exampleid" class="exampleClass"/>

Documentation

Follow standard for PyDocStyle

This standard needs to be satisfied in order for your code to be merged into master branch (this standard is checked by flake8 with flake8_docstrings plugin)

Do not leave code in comments

  • Code in comments are confusing for reader, because they cannot distinguish comment from unused code
  • For old code, we have version control (git) we can always find the old code, leave the old code in comment is redundant
  • For experiment code, you can open an issue. If we decide your idea is really good but not for now, we can always open a new page in wiki

Comment syntax

Comment syntax follows the default Pycharm comment syntax.

YES 👍:

def __init__(self, word_list, file_name):
    """Calculate all the information of the given file.

    :param word_list: a dictionary map word to word count representing the
                        word count of particular file
    :param file_name: the file name of that file
    """

NO 👎:

def __init__(self, word_list, file_name):
    """
    Calculate all the information of the given file.

    Args:
        word_list: a dictionary map word to word count representing the
                        word count of particular file
        file_name: the file name of that file
    
    Returns:
        None
    """

The formal syntax of the doc string should be as follow:

"""One line summary, ends with period; the next line needs to be empty.

Multiline description (optional).
:para para_name1: para description 1 (optional).
:para para_name2: para description 2 (optional).
:return: description of the variable returned (optional).
"""

or

"""One line doc string, ends with period."""

Keep Your Function Thin

Typically dividing your functions into smaller function will help you to modulize your application.

Keep your function short

A good rule of thumb is do not make your function longer than 30 lines. This will make keeping track of what you are doing much more easier.

Keep your function flat

A good rule of thumb is that you cannot have more than 12 space indenting (no more than 3 indenting structure).

When you have more and more indentations python became less and less readable, and it will be harder and harder to keep your line under 79 chars.

YES 👍:

class ExampleClass:
    
    # create private helper function when your logic is too complicated
    function __do_something_for_elem__(element):  # first indenting structure
        if element.property is True: # second indenting structure
            do_lots_of_things()   # third indenting structure

    function do_something_for_list(input_list):  # first indenting structure
         for element in input_list:  # second indenting structure
             __do_something_for_elem__(element)  # third indenting structure

NO 👎:

class ExampleClass:

    function do_something_for_list(input_list):  # first indenting structure
         for element in input_list:  # second indenting structure
             if element.property is True: # third indenting structure
                 do_lots_of_things()  # forth indenting structure, NOOOOOO!

Use Keyword Parameter

Typically using keyword parameter will make your code easy to understand:

YES 👍:

generate_matrix(use_freq=True,
                token_type="by_gram",
                token_size=2)

NO 👎:

generate_matrix(True, "by_gram", 2)

There is a few exceptions:

YES 👍:

sin_of_x = sin(x)

NO 👎:

sin_of_x = sin(value=x)

Make Sure PyCharm is Happy with Your Code

when you are done with your code, pycharm should give you no error or warnings.

NO 👎:

if some_variable is True:
    other_variable = False

print(other_variable)  # pycharm will give you an warning here

YES 👍:

if some_variable is True:
    other_variable = False
else:
    other_variable = True

print(other_variable)  # pycharm is happy

Avoid Mutating your variable

Hard as this is to believe, in most case you really do not need to mutate your variable.

list comprehension helps you a great deal.

YES 👍:

def zip_and_shift_to_positive(x_coords, y_coords):
    """
    current function zips two list: xs and ys to xy_coord_list
    and then shifts the whole graph to make all the coord positive
    """
    # zip list
    xy_coord_list = zip(x_coords, y_coords)

    # shifts the list
    x_shift = min(x_coords)
    y_shift = min(y_coords)
    positive_coord_list = [[x - x_shift, y - y_shift] for x, y in coord_list]
    
    return positive_coord_list

NO 👎:

def zip_and_shift_to_positive(x_coords, y_coords):
    x_shift = min(x_coords)
    y_shift = min(y_coords)
    
    # should use list comprehension
    positive_coord_list = []
    for index in range(len(x_coords)):
        # very dangerous, since list is pass by refrence, 
        # editing list in function can easily render unwanted result
        x_coords[i] -= x_shift 
        y_coords[i] -= y_shift

        positive_coord_list.append([x_coords[i], y_coords[i]])  # append is much slower than list comprehension
    
    return positive_coord_list

When you want to mutate your variable, you can probably give it a new variable name

YES 👍:

my_sorted_list = sorted(my_list)

NO 👎:

my_list = sorted(my_list)

when you give your variable a new name, you are giving the variable a more accurate description, therefore makes the code more clear.

NEVER mutate the type of a variable

Python gives you the freedom to mutate the type of a variable (dynamically typed), but majority of programmer still thinks static typing provides better security to the program.

Also, if you mutate the type of the variable, it is probably not the same thing as before. Therefore you should give the variable a new name.

YES 👍:

json_dict = {'hello': 'lala', 'tata': 'haha'}
json_str = json.dump(json_dict)

NO 👎:

json_dict = {'hello': 'lala', 'tata': 'haha'}
json_dict = json.dump(json_dict)

As you can see, when you do a json.dump on the dict, it becomes a string. Therefore a more accurate description of the variable is not json_dict but json_str

Clone this wiki locally