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:
Specification | Description |
---|---|
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 |
line length | No more than 80 characters per line |
brackets | Do not use too more brackets |
Indent | Use 4 spaces to indent the code |
blank line | Two blank lines between top-level definitions and one blank line between method definitions |
space | Use the spaces on both sides of the punctuation in accordance with the standard typesetting conventions |
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 |
Class | If a class does not inherit from other classes, it explicitly inherits from Object |
String | Try to use% or formatting method to format the string |
Files and Sockets | At the end of the file and Sockets, explicitly close |
TODO | Use TODO comments for temporary code |
Import format | Each import should be on its own line |
Sentence | Each statement should be on its own line |
Access control | For trivial and unimportant access functions, use global variables instead |
Name | Single-character, dash (-), double-underline and other naming methods should be avoided |
Main | Even 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(kl@gmail.com): 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:
- Standard module import
- Third-party module import
- 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:
Type | Public | Internal |
---|---|---|
Modules | lower_with_under | lower_with_under |
Packages | lower_with_under | |
Classes | CapWords | _CapWords |
Exceptions | CapWords | |
Functions | lower_with_under() | _lower_with_under() |
Global/Class Constant | CAPS_WITH_UNDER | _CAPS_WITH_UNDER |
Global/Class Variables | lower_with_under | _lower_with_under |
Instance Variables | lower_with_under | _lower_with_under (protect) __lower_with_under(private) |
Method Names | lower_with_under() | _lower_with_under() (protect) __lower_with_under() (private) |
Function/Method Parameters | lower_with_under | |
Local Variables | lower_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.