Skip to content

[Python] A Note About Coding Style Recommended By Google

Recently, I have to complete a personal side project and transfer to my friend, he want to continue to add some features he wants.

Because of this, I began to consider whether to organize the code thoroughly.

In fact, I think the important thing is to keep the coding style consistent from beginning to end. The other thing is to communicate with your team.

However, since I have decided to thoroughly organize my own code and give it to others to take over, I think it’s always good to refer to the style guidelines suggested by masters and great gods.

This article mainly records a note called Google Python Style Guide.

In here, I would like to thank the original author very much:

- Amit Patel
- Antoine Picard
- Eugene Jhong
- Jeremy Hylton
- Matt Smart
- Mike Shields

So, the following is the Python style guide as defined in the Google open source project style guide:

SpecificationDescription
semicolonDo not add a semicolon at the end of the line, and do not use a semicolon to put two commands on the same line
line lengthNo more than 80 characters per line
bracketsDo not use too more brackets
IndentUse 4 spaces to indent the code
blank lineTwo blank lines between top-level definitions and one blank line between method definitions
spaceUse the spaces on both sides of the punctuation in accordance with the standard typesetting conventions
ShebangMost .py files do not have to start with #! as the file
CommentMake sure to use the correct style for modules, functions, methods, and inline comments
ClassIf a class does not inherit from other classes, it explicitly inherits from Object
StringTry to use% or formatting method to format the string
Files and SocketsAt the end of the file and Sockets, explicitly close
TODOUse TODO comments for temporary code
Import formatEach import should be on its own line
SentenceEach statement should be on its own line
Access controlFor trivial and unimportant access functions, use global variables instead
NameSingle-character, dash (-), double-underline and other naming methods should be avoided
MainEven script files should be importable

The following introduction will have a list of descriptions and sample programs. Only the words in bold are my personal opinion, there may be errors, please refer to it as appropriate.


Semicolon

Do not add a semicolon at the end of the line, and do not use a semicolon to put two commands on the same line
# No
a = 1;
b = 1; c = a + b

# Yes
a = 1
b = 1
c = a + b



Line Length

No more than 80 characters per line.

This is easy to understand, and too long code will cause obstacles in reading comprehension.


Brackets

Do not use too more brackets.
  • Don not use it when the function returns
  • Do not use in conditional expressions
  • Tuple can be used
# No
return (x, y)
if (x and y): ...


# Yes
return x, y
if x and y



I personally prefer this to be a matter of habit…… But I agree not to add parentheses. The code looks clearer.


Indent

Use 4 spaces to indent the code.
  • Do not use TAB
  • Align elements when wrapping
# No
id2value = {
    1: 10,
2: 20,
3: 30,
}


# Yes
id2value = {
    1: 10,
    2: 20,
    3: 30,
}



Since Python strictly needs to use "indentation" to distinguish code blocks, such as For loops or functions, mixed use of blanks or TAB will cause the Python interpreter to report "indentation errors".

In addition, the alignment of elements is for aesthetics and to reduce the burden on readers.


Blank Line

Two blank lines between top-level definitions and one blank line between method definitions.
  • Two blank lines between functions
  • Two blank lines between Class
  • One blank line between Method
  • If some places feel suitable, just leave a line blank (?)
# No
def x():
    ...
def y():
    ...

# Yes
def x():
    ...


def y():
    ...


# No
class x:
    def __init__(self):
        ...


    def process(self):
        ...

# Yes
class x:
    def __init__(self):
        ...

    def process(self):
        ...



This part is just a unified format. The biggest problem is that the description of "blank a line if you think it fits" is very vague.

I myself will leave a blank line at the top when I encounter loops or conditional judgments.


Space

Use the spaces on both sides of the punctuation in accordance with the standard typesetting conventions
  • Do not add spaces before commas, semicolons, and colons, but you need to add spaces after them
  • Spaces should be added to the left and right of the operator
# No
a,b,c=1,2,3



# Yes
a, b, c = 1, 2, 3



Shebang

Most .py files do not have to start with #! as the file

Comment

Make sure to use the correct style for modules, functions, methods, and inline comments
  • Python convention uses triple double quotation marks """ as document string characters
  • Comments can describe the name and function of each parameter (Args)
  • Annotation can describe the type and semantics of the return value (Returns)
  • Comments can describe all exceptions of the function interface (Raises)
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
    """Fetches rows from a Bigtable.

    Retrieves rows pertaining to the given keys from the Table instance
    represented by big_table.  Silly things may happen if
    other_silly_variable is not None.

    Args:
        big_table: An open Bigtable Table instance.
        keys: A sequence of strings representing the key of each table row
            to fetch.
        other_silly_variable: Another optional variable, that has a much
            longer name than the other args, and which does nothing.

    Returns:
        A dict mapping keys to the corresponding table row data
        fetched. Each row is represented as a tuple of strings. For
        example:

        {'Serak': ('Rigel VII', 'Preparer'),
         'Zim': ('Irk', 'Invader'),
         'Lrrr': ('Omicron Persei 8', 'Emperor')}

        If a key from the keys argument is missing from the dictionary,
        then that row was not found in the table.

    Raises:
        IOError: An error occurred accessing the bigtable.Table object.
    """
    pass


  • To explain the tricky part of the code, use # comments at the end of the line
  • The comment should be at least 2 spaces away from the code
# No
if i & (i-1) == 0:# true iff i is a power of 2


# Yes
if i & (i-1) == 0: # true iff i is a power of 2



Class

If a class does not inherit from other classes, it explicitly inherits from Object
  • Inheriting Object is to make properties work properly
# No
class SampleClass:
    pass


# Yes
class SampleClass(object):
    pass



String

Try to use% or formatting method to format the string.
  • Avoid using + or += to increase the string, it will create unnecessary temporary objects
  • Add the string to the list, use join() to connect the string
# No
string = ''
for item in items:
    string += item


# Yes
string = []
for item in items:
    string.append(item)

string = ''.join(item)



Files and Sockets

At the end of the file and Sockets, explicitly close.
  • Not shutting down will consume system resources
  • Different Python memory management technologies are not guaranteed to be the same
  • It is recommended to use with to manage files

This is a mistake I often make… I never thought about it so dangerous before carefully reviewing this document.


TODO

Use TODO comments for temporary code
  • TODO comments should contain the "TODO" string at the beginning
  • Should leave the name of the developer, Email
  • Explain what to do
# TODO([email protected]): Use a "*" here for string repetition.
# TODO(Zeke) Change this to use relations.



Import Format

Each import should be on its own line.
# No
import os, sys

# Yes
import os
import sys


  • Import should be at the beginning of the file
  • Import should be after module comment and document string
  • Import should be before the code

Imports should have a fixed order:

  1. Standard module import
  2. Third-party module import
  3. other

The import order is sorted alphabetically:

import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar



Sentence

Each statement should be on its own line.
# No
if foo: bar(foo)
else: baz(foo)

try: bar(foo)
except ValueError: baz(foo)

# Yes
if foo:
    bar(foo)
else:
    baz(foo)

try:
    bar(foo)
except ValueError:
    baz(foo)



Access Control

For trivial and unimportant access functions, use global variables instead,

The document here only says to try to accept the Pythonic philosophy =D

I think it is actually very convenient to directly use global variables unless it is really too efficient.


Name

Single-character, dash (-), double-underline and other naming methods should be avoided
  • Except for counting and iteration, single characters should not be used
  • The dash (-) symbol should not be used, it should be used for the package or module name
  • xx reserves a name for Python

Recommended specifications:

TypePublicInternal
Moduleslower_with_underlower_with_under
Packageslower_with_under
ClassesCapWords_CapWords
ExceptionsCapWords
Functionslower_with_under()_lower_with_under()
Global/Class ConstantCAPS_WITH_UNDER_CAPS_WITH_UNDER
Global/Class Variableslower_with_under_lower_with_under
Instance Variableslower_with_under_lower_with_under (protect)
__lower_with_under(private)
Method Nameslower_with_under()_lower_with_under() (protect)
__lower_with_under() (private)
Function/Method Parameters lower_with_under
Local Variableslower_with_under

Main

Even script files should be importable.
# Yes
def main():
    ...

if __name__ == '__main__':
    main()



Ashamed… I have a lot of programs that simply execute and test certain components. They are written from top to bottom like scripts.

However, if you really develop the functions you want to use, you will well abide by such format specifications.


References

Tags:

Leave a Reply