Skip to content

VantTec Python Standard

vSebas edited this page Jan 30, 2020 · 11 revisions

VANTTEC PYTHON STANDARD

The VantTec Python standard is based on the PEP 8 -- Style Guide for Python Code and the The Hitchhiker’s guide to Python

For recommendations and modifications, please refer to Pedro Sanchez, Roberto Mendivil or Sebastian Martinez

Here you have the collection of the 19 "guiding principles" that you should take into consideration when writing Python Code.

Look at this script for references on how to write good Python code: https://github.com/hblanks/zen-of-python-by-example/blob/master/pep20_by_example.py


CODE LAYOUT

Indentation

  • Do not use tab, use four spaces instead per indentation level.
  • Continuation lines should align wrapped elements using a hanging indent. When using a hanging indent the following should be considered; there should be no arguments on the first line and further indentation should be used to clearly distinguish itself as a continuation line.

# Aligned with opening delimiter.

foo = long_function_name(var_one, var_two,
                         var_three, var_four)

# Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest.

def long_function_name(

        var_one, var_two, var_three,

        var_four):

    print(var_one)

# Hanging indents should add a level.

foo = long_function_name(

    var_one, var_two,

    var_three, var_four)
  • The closing brace/bracket/parenthesis on multiline constructs may either be like this:

      my_list = [
    
          1, 2, 3, 4
    
      ]
    
      or this:
    
      my_list = [
    
          1,2,3,4
    
      ]
    

Maximum Line Length

Limit all lines to a maximum of 80 characters. If the length of a line is larger than 80 characters, try to use a “space + backslash”. With this, the editor will detect it is a line continuation marker.

with open('/path/to/some/file/you/want/to/read') as file_1, \

     open('/path/to/some/file/being/written', 'w') as file_2:

    file_2.write(file_1.read())

However, there could be some exceptions, like when dealing with ROS Topics, paths or similar.

Line Break

# Yes: easy to match operators with operands

income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

Blank Lines

  • Surround top-level function and class definitions with two blank lines. (IMPORTANT!)
  • Method definitions inside a class are surrounded 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.

Source File Encoding and Interpreter

At the beginning of every script you should add these lines:

#!/usr/bin/env python

This means that the program loader takes the presence of “#!” as an indication that the file is a script, and tries to execute that script using the interpreter specified by the rest of the first line in the file.

# -*- coding: utf-8 -*-

Code in the core Python distribution should always use UTF-8 (or ASCII in Python 2). Files using ASCII (in Python 2) or UTF-8 (in Python 3) should not have an encoding declaration.

Imports

  • Imports should be on separate lines

      YES: 
      import os
      import sys
    
      NO:
      import os, sys
    
      It is okay to do 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.

  • Do not use: from <library> import *

  • Imports should be grouped in the following order

    1. Standard imports
    2. Related third party imports
    3. Local application / library specific imports
    4. When importing a class from a class from Class import MyClass

String quotes

In Python, double-quoted strings and single-quoted strings are the same, however, double quotes will only be used when dealing with paths and topics (ROS).


Whitespace in expressions and statements

  • 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 } )
      
    • Between a trailing comma and a following close parenthesis.

       YES: foo = (0,)
      
       NO: bar = (0, )
      
    • 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
      
  • 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).

      YES:
    
      i = i + 1
    
      submitted += 1
    
      x = x*2 -1
    
      hypot2 = x*x + y*y
    
  • Don't use spaces around the = sign when used to indicate a keyword argument, or when used to indicate a default value for an unannotated function parameter.

      YES:
    
      def complex(real, imag=0.0):
    
          return magic(r=real, i=imag)
    

Naming conventions

Classes

With CapWords

class MyClass

Objects

With camelCase

autoNav = AutoNav()

Global Variables

(Let's hope that these variables are meant for use inside one module only.) The conventions are about the same as those for functions. Modules that are designed for use via from M import * should use the all mechanism to prevent exporting globals, or use the older convention of prefixing such globals with an underscore (which you might want to do to indicate these globals are "module non-public").

Functions and Variable Names

  • For functions, with lowercase_and_underscore

  • For variables,also with lowercase_and_underscore

    • Variable names follow the same convention as function names. Never use names such as I (i), l (L), O or o.
  • mixedCase is allowed only in contexts where that's already the prevailing style (e.g. threading.py), to retain backwards compatibility.

Functions and Method Arguments

  • Always use self for the first argument to instance methods
  • Always use cls for the first argument to class methods
    • More info about this here
  • Function and method arguments should be named with a _leading_underscore_lowercase_and_more_underscores

Comments

Comments at the beginning of files

'''

   ----------------------------------------------------------------------------------

   @file: file.cpp

   @date: Thu Dec 26, 2019

   @date_modif: Thu Dec 28, 2019

   @author: name

   @e-mail:        

   @co-author: (If multiple co-authors, write the name and e-mail of each one)

   @e-mail:

   @brief:

   @version:

   ----------------------------------------------------------------------------------

'''

Class Comments

Comment before class only if it not descriptive

Functions Comments

'''
   ---------------------------------------------------------
   @name:

   @brief:

   @param:   a[in]:  describe 

             b[out]: describe

   @return
  ---------------------------------------------------------
'''

More Tips

If you use Visual Studio Code as your code editor, you can add a vertical line into your screen, so you can see where your line should end. Just go to File >> Preferences >> Settings >> search for Editor:Rulers and in the json file just paste this:

"editor.rulers": [80]

One statement per line

It is bad practice to have two disjointed statements on the same line of code

cond1 = <Complex comparison>
cond2 = <Complex comparison>

if cond1 and cond2:
    # do something

Create a length-N list of the same thing

Use the Python list * operator:

four_name = [None] * 4

Create a length-N list of lists

Because lists are mutable, the * operator (as above) will create a list of N references to the same list, which is not likely what you want. Instead, use a list comprehension:

four_lists = [[] for_in xrange(4)]

Create a string from a list

A common idiom for creating strings is to use str.join() on an empty string.

letter = ['s', 'p', 'a', 'm']
word = a.join(letter)

Searching for an item in a collection

Use sets or dictionaries instead of lists in cases where:

  • The collection will contain a large number of items

  • You will be repeatedly searching for items in the collection

  • You do not have duplicate items.

     s = set(['s', 'p', 'a', 'm'])
    
     l = set(['s', 'p', 'a', 'm'])
    
     return 'p' in s   #faster set search
     return 'p' in l