Google Python Programming Style Guide

Python is Google's main scripting language. This style guide mainly contains programming guidelines for python.

background

To help readers format the code accurately, we provide a configuration file for Vim. For Emacs users, just keep the default settings.

Python language specification

Lint

Run pylint on your code

Definition: pylint is a tool for finding bugs in Python source code. For less dynamic languages like C and C++, these bugs are usually caught by the compiler. Due to the dynamics of Python Features, some warnings may be wrong. But false warnings should be few. Advantages: It can catch errors that are easy to ignore, such as input errors, use of unassigned variables, etc. Disadvantages: pylint is not perfect. To take advantage of its advantages, we sometimes need: a) write code around it b) suppress its warning c) improve it, or d) ignore it. Conclusion: make sure to run pylint on your code. Suppress inaccurate warnings so that other warnings can be exposed. You can suppress the warning by setting a line comment. For example:

dict ='something awful'  # Bad Idea... pylint: disable=redefined-builtin

The pylint warning is identified by a numeric number (such as C0112) and a symbolic name (such as empty-docstring). When writing new code or updating existing code, the warning is treated. It is recommended to use symbolic names to identify .

If the symbol name of the warning is not enough to be understood, please add a detailed explanation.

The advantage of adopting this suppression method is that we can easily find suppressions and review them.

You can use the command pylint --list-msgs to get a list of pylint warnings. You can use the command pylint --help-msg=C6409 to get more information about a specific message.

Compared with the previously used pylint: disable-msg, this article recommends using pylint: disable.

To suppress the "parameter not used" warning, you can use "" as a parameter identifier, or add "unused" in front of the parameter name. When you encounter a situation where the parameter name cannot be changed, you can "mentioned" them at the beginning of the function Eliminate the warning. For example:

def foo(a, unused_b, unused_c, d=None, e=None):
_ = d, e    return a

Import##

Use imports only for packages and modules

Definition: A reuse mechanism for sharing code between modules. Advantages: The namespace management convention is very simple. The source of each identifier is indicated in a consistent way. x.Obj means that the Obj object is defined in module x. Disadvantage: module name There may still be conflicts. Some module names are too long to be convenient. Conclusion: Use import x to import packages and modules. Use from x import y, where x is the package prefix and y is the module name without the prefix. Use from x import y as z, if the two modules to be imported are called y or y is too long. For example, the module sound.effects.echo can be imported as follows:

from sound.effects import echo
...
echo.EchoFilter(input, output, delay=0.7, atten=4)

Do not use relative names when importing. Even if the modules are in the same package, use the full package name. This helps you avoid accidentally importing a package twice.

package##

Use the full path name of the module to import each module

Advantages: Avoid module name conflicts. It is easier to find packages. Disadvantages: It is difficult to deploy code because you have to copy the package hierarchy. Conclusion: All new code should use the full package name to import each module. It should be imported as follows:

# Reference in code with complete name.import sound.effects.echo# Reference in code with just module name(preferred).from sound.effects import echo

abnormal##

Exceptions are allowed, but care must be taken

Definition: An exception is a way to break out of the normal control flow of a code block to handle errors or other abnormal conditions. Advantages: The control flow of the normal operation code will not be mixed with the error handling code. When a certain condition occurs, it also allows Control flow skips multiple frames. For example, jump out of N nested functions in one step without continuing to execute the wrong code. Disadvantages: may lead to confusing control flow. It is easy to miss error conditions when calling the library. Conclusion: Exception Certain conditions must be observed:

Trigger an exception like this: raise MyException("Error message") or raise MyException. Do not use the two-parameter form (raise MyException, "Error message") or outdated string exception (raise "Error message" ).

The module or package should define its own domain-specific exception base class. This base class should inherit from the built-in Exception class. The module's exception base class should be called "Error".

classError(Exception):
pass

Never use the except: statement to catch all exceptions, and do not catch Exception or StandardError unless you intend to re-trigger the exception, or you are already in the outermost layer of the current thread (remember to still print an error message ). In terms of exceptions, Python is very tolerant, except: will really catch any errors including Python syntax errors. Using except: is easy to hide real bugs.

Try to minimize the amount of code in the try/except block. The larger the try block, the easier it is to trigger unexpected exceptions. In this case, the try/except block will hide the real error.

Use the finally clause to execute code that should be executed regardless of whether there are exceptions in the try block. This is often useful for cleaning up resources, such as closing files.

When catching exceptions, use as instead of commas. For example

try:    raise Errorexcept Error as error:    pass

Global variables##

Avoid global variables

Definition: Variables defined at the module level. Advantages: occasionally useful. Disadvantages: module behavior may be changed when importing, because module-level variables are assigned when importing modules. Conclusion: avoid using global variables and use class variables instead. But there are some exception:

The default options for the script.

Module-level constants. For example: PI = 3.14159. Constants should be all uppercase and connected with underscores. Sometimes it is useful to use global variables to cache values or return values as functions. If necessary, global variables should only be available inside the module and passed through the module Level public functions to access.

Nested/local/inner class or function##

Encourage the use of nested/local/inner classes or functions

Definition: Classes can be defined in methods, functions or classes. Functions can be defined in methods or functions. Variables defined in the enclosed range are read-only for nested functions. Advantages: Allows to define tool classes and classes that are only used in the effective scope Functions. Disadvantages: Instances of nested classes or local classes cannot be serialized (pickled). Conclusion: Recommended.

List Comprehensions

Can be used in simple cases

Definition: List comprehensions and generator expressions provide a simple and efficient way to create lists and iterators without having to resort to map(), filter(), or lambda. Advantages: simple List comprehensions can be clearer and simpler than other list creation methods. Generator expressions can be very efficient because they avoid creating the entire list. Disadvantages: complex list comprehensions or generator expressions can be difficult to read. Conclusion: Suitable for simple situations . Each part should be placed on a separate line: mapping expressions, for statements, filter expressions. Multiple for statements or filter expressions are prohibited. In complex cases, loops are still used.

Yes:
result =[]for x inrange(10):for y inrange(5):if x * y >10:
    result.append((x, y))for x inxrange(5):for y inxrange(5):if x != y:for z inxrange(5):if y != z:yield(x, y, z)return((x,complicated_transform(x))for x inlong_generator_function(parameter)if x is not None) squares =[x * x for x inrange(10)]eat(jelly_bean for jelly_bean in jelly_beans      if jelly_bean.color =='black')
No:
result =[(x, y)for x inrange(10)for y inrange(5)if x * y >10]return((x, y, z)for x inxrange(5)for y inxrange(5)if x != y          for z inxrange(5)if y != z)

Default iterators and operators##

If the type supports it, the default iterators and operators are used. For example, lists, dictionaries and files, etc.

Definition: Container types, like dictionaries and lists, define default iterators and relational test operators (in and not in). Advantages: The default operators and iterators are simple and efficient. They directly express operations without additional method calls. The function using the default operator is universal. It can be used for any type that supports the operation. Disadvantage: you can't distinguish the type of the object by reading the method name (for example, has_key() means a dictionary). But this is also an advantage Conclusion: If the type supports it, use the default iterators and operators, such as lists, dictionaries and files. Built-in types also define iterator methods. These methods are given priority over those that return lists. Of course, iterate like this When container, you will not be able to modify the container.

Yes:for key in adict:...if key not in adict:...if obj in alist:...for line in afile:...for k, v in dict.iteritems():...
No:for key in adict.keys():...if not adict.has_key(key):...for line in afile.readlines():...

Builder##

Use generators on demand.

Definition: The so-called generator function means that every time it executes a yield statement, it returns an iterator, and this iterator generates a value. After the value is generated, the running state of the generator function will be suspended until the next One-time generation. Advantages: Simplify the code, because every time it is called, the state of local variables and control flow will be saved. Compared to functions that create a series of values at a time, the generator uses less memory. Disadvantages: No. Conclusion: Encouragement Use. Note the use of "Yields:" instead of "Returns:" in the docstring of the generator function. (Translator's Note: see comments)

Lambda function##

Suitable for one-line functions

Definition: Contrary to a statement, lambda defines an anonymous function in an expression. It is often used to define callback functions or operators for higher-order functions such as map() and filter(). Advantages: convenience. Disadvantages: better than Local functions are more difficult to read and debug. No function name means that the stack trace is more difficult to understand. Since lambda functions usually contain only one expression, their expressive power is limited. Conclusion: Suitable for single-line functions. If the code exceeds 60-80 characters , It is better to define as a regular (nested) function. For common operators, such as multiplication operators, use functions in the operator module instead of lambda functions. For example, it is recommended to use operator.mul instead of lambda x, y: x * y.

Conditional expression##

Suitable for one-line functions

Definition: Conditional expression is a shorter syntax rule for if statement. For example: x = 1 if cond else 2. Advantage: shorter and more convenient than if statement. Disadvantage: harder to read than if statement. If The expression is very long and it is difficult to locate the condition. Conclusion: Suitable for one-line functions. In other cases, it is recommended to use a complete if statement.

Default parameter value##

Suitable for most situations.

Definition: You can specify the value of the variable at the end of the function parameter list, for example, def foo(a, b = 0):. If you call foo with only one parameter, then b is set to 0. If you take two Parameter, then the value of b is equal to the second parameter. Advantages: You often encounter some functions that use a large number of default values, but occasionally (rarely) you want to override these default values. The default parameter values provide a simple To accomplish this, you don’t need to define a large number of functions for these rare exceptions. At the same time, Python does not support overloaded methods and functions. Default parameters are a simple way to "fake" overloading behavior. Disadvantages: Default parameters It is evaluated only once when the module is loaded. If the parameter is a variable type such as a list or dictionary, this may cause problems. If the function modifies the object (for example, appends an item to the list), the default value is modified. Conclusion: Use is encouraged, but there are precautions as follows: Do not use mutable objects as default values in function or method definitions.

Yes: def foo(a, b=None):if b is None:
b =[]
No:  def foo(a, b=[]):...
No:  def foo(a, b=time.time()):  # The time the module was loaded???...
No:  def foo(a, b=FLAGS.my_thing):  # sys.argv has not yet been parsed......

Properties

When accessing and setting data members, you usually use simple, lightweight access and setting functions. It is recommended to use properties instead of them.

Definition: A way to wrap method calls. When the amount of calculation is not large, it is a standard way to get and set attributes. Advantages: Explicit get and set methods by eliminating simple attribute access Calling, readability is improved. Lazy calculations are allowed. The interface of the class is maintained in a Pythonic way. In terms of performance, when direct access to variables is reasonable, adding access methods is trivial and meaningless. Use properties (properties ) Can bypass this problem. In the future, you can also add access methods without breaking the interface. Disadvantages: properties are specified after the get and set method declarations, which requires the user to pay attention to the following code : set and get are used for properties (except for read-only properties created with the @property decorator). Must inherit from the object class. It may hide side effects such as operator overloading. Inheritance may make people Confused. Conclusion: You are usually used to access or set data using access or setting methods. They are simple and lightweight. However, we recommend that you use properties in new code. Read-only properties should be created with the @property decorator If the subclass does not override the property, then the inheritance of the property may not seem obvious. Therefore, the user must ensure that the access method is called indirectly to ensure that the overloaded method in the subclass is called by the property (using the template method design pattern).

Yes:import math     classSquare(object):"""A square with two properties: a writable area and a read-only perimeter.        To use:>>> sq =Square(3)>>> sq.area
  9>>> sq.perimeter
  12>>> sq.area =16>>> sq.side
  4>>> sq.perimeter
  16"""  def __init__(self, side):
   self.side = side         def __get_area(self):"""Calculates the 'area' property."""return self.side **2        def ___get_area(self):"""Indirect accessor for 'area' property."""return self.__get_area()         def __set_area(self, area):"""Sets the 'area' property."""
   self.side = math.sqrt(area)         def ___set_area(self, area):"""Indirect setter for 'area' property."""
   self._SetArea(area)        area =property(___get_area, ___set_area,
      doc="""Gets or sets the area of the square.""")         @property
  def perimeter(self):return self.side *4

( Translator's Note: To be honest, I think this sample code is very inappropriate, is it necessary to be so painful?)

Evaluation of True/False##

Use implicit false whenever possible

Definition: Python evaluates certain values to false in a Boolean context. According to simple intuition, all "empty" values are considered false. Therefore, 0, None, [], {}, "" Both are considered false. Advantages: Conditional statements that use Python booleans are easier to read and less likely to make mistakes. In most cases, they are also faster. Disadvantages: For C/C++ developers, it may seem a bit strange. Conclusion: Use implicit false as much as possible, for example: use if foo: instead of if foo != []:. However, there are some caveats that you should keep in mind:

Never use == or != to compare single items, such as None. Use is or is not. Note: When you write if x:, you actually mean if x is not None. For example: When you want to test whether a variable or parameter whose default value is None is set to another value. This value may be false in Boolean semantics!

Never use == to compare a boolean to false. Use if not x: instead. If you need to distinguish between false and None, you should use statements like if not x and x is not None:. For sequences (strings, lists, tuples), note that the empty sequence is false. So if not seq: or if seq: is better than if len(seq): or if not len(seq): To be better.

When dealing with integers, the use of implicit false may outweigh the gain (that is, accidentally treating None as 0). You can compare a value that is known to be an integer (and not the return result of len()) with 0.

Yes:if not users:         print 'no users'if foo ==0:         self.handle_zero()if i %10==0:         self.handle_multiple_of_ten()
No:iflen(users)==0:         print 'no users'if foo is not None and not foo:
self.handle_zero()if not i %10:
self.handle_multiple_of_ten()

Note that '0' (string) will be treated as true.

Outdated language features##

Use string methods instead of string modules as much as possible. Use function call syntax instead of apply(). Use list comprehensions and for loops instead of filter(), map() and reduce().

Definition: The current version of Python provides alternatives that people usually prefer. Conclusion: We do not use a version of Python that does not support these features, so there is no reason not to use new methods.

Yes: words = foo.split(':')[x[1]for x in my_list if x[2]==5]map(math.sqrt, data)    # Ok. No inlined lambda expression.fn(*args,**kwargs)
No:  words = string.split(foo,':')map(lambda x: x[1],filter(lambda x: x[2]==5, my_list))apply(fn, args, kwargs)

Lexical Scoping

Recommended Use

Definition: Nested Python functions can refer to variables defined in the outer function, but cannot assign values to them. The analysis of variable binding uses lexical scope, which is based on static program text. For a certain block in a block Any assignment of a name will cause Python to treat all references to the name as local variables, even the processing before assignment. If a global declaration is encountered, the name will be treated as a global variable. An example of using this feature:

def get_adder(summand1):"""Returns a function that adds numbers to a given number."""
def adder(summand2):return summand1 + summand2    return adder

( Translator's Note: This example is a bit weird, you should use this function like this: sum = get_adder(summand1)(summand2))

Advantages: usually can bring clearer and more elegant code. Especially experienced Lisp and Scheme (and Haskell, ML, etc.) programmers feel relieved. Disadvantages: may lead to confusing bugs. For example, the following is based on PEP -0227 example:

i = 4def foo(x):
def bar():
print i,    # ...
# A bunch of code here
# ... for i in x:  # Ah, i *is* local to Foo, so this is what Bar sees
print i,bar()

So foo([1, 2, 3]) will print 1 2 3 3, not 1 2 3 4.

( Translator's Note: x is a list, and the for loop actually assigns the values in x to i in turn. The assignment to i will happen implicitly, and the i in the entire foo function body will be treated as a local variable, including bar The one in (). This is still very different from static languages such as C++.)

Conclusion: encourage use.

Function and method decorator##

If the benefits are obvious, use decorators wisely and carefully.

Definition: Decorator used for functions and methods (that is, @mark). The most common decorators are @classmethod and @staticmethod, which are used to convert regular functions into class methods or static methods. However, the decorator syntax also allows users Custom decorator. In particular, for a function my_decorator, the following two pieces of code are equivalent:

classC(object):   @my_decorator
def method(self):
# method body ...
classC(object):
def method(self):
# method body ...
method =my_decorator(method)

Advantages: gracefully specify some conversions on functions. This conversion may reduce some duplication of code, keep existing functions unchanged (enforce invariants), etc. Disadvantages: decorators can perform any operation on the parameters or return values of functions, this May cause amazing hidden behavior. Moreover, decorators are executed at import time. It is even more impossible to recover from failure of decorator code. Conclusion: If the benefits are obvious, use decorators wisely and carefully. Decorators should follow The same import and naming rules as functions. The python documentation of the decorator should clearly state that the function is a decorator. Please write unit tests for the decorator. Avoid the decorator's own dependence on the outside world (ie don't rely on files, sockets, etc.) Database connection, etc.), because these resources may not be available when the decorator is running (imported by pydoc or other tools). It should be ensured that a decorator called with valid parameters is successful in all cases. A decorator is a kind of Special form of "top-level code". Refer to the topic on Main later.

Thread##

Don't rely on the atomicity of built-in types.

Although Python's built-in types such as dictionaries seem to have atomic operations, in some cases they are still not atomic (i.e. if hash or eq are implemented as Python methods) and their atomicity is unreliable You also cannot count on atomic variable assignment (because this in turn depends on the dictionary).

Use the Queue data type of the Queue module as the data communication method between threads. In addition, use the threading module and its locking primitives. Know the appropriate use of condition variables, so you can use threading.Condition To replace low-level locks.

Overpowering features##

Avoid using these features

Definition: Python is an extremely flexible language. It provides you with many fancy features, such as metaclasses, bytecode access, on-the-fly compilation, dynamic inheritance, object parent classes Redefinition (object reparenting), import hacks, reflection, modification of system internals, etc. Advantages: powerful language features can make your code more compact. Disadvantages: using these is very" The "cool" feature is very tempting, but not absolutely necessary. Codes that use fancy tricks will be more difficult to read and debug. It may be good at first (for the original author), but when you review the code, they may be better than those Longer but straightforward code is more difficult to understand. Conclusion: Avoid these features in your code.

Python style guidelines#

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

Exception: Do not use backslashes to connect lines in URLs in long import module statement comments.

Python will implicitly concatenate parentheses, square brackets and curly braces. You can take advantage of this feature. If necessary, you can add a pair of extra parentheses around the expression.

Yes:foo_bar(self, width, height, color='black', design=None, x='foo',
emphasis=None, highlight=0)if(width ==0 and height ==0 and
color =='red' and emphasis =='strong'):

If a text string does not fit on one line, you can use parentheses to achieve implicit line concatenation:

x =('This will build a very long long ''long long long long long long string')

In the comments, if necessary, put the long URL on one line.

Yes:  # See details at
# http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html
No:  # See details at
# http://www.example.com/us/developer/documentation/api/content/\
# v2.0/csv_file_name_extension_full_specification.html

Note the indentation of the elements in the example above; you can find an explanation in the indentation section of this article.

brackets##

Ning Quewu use parentheses indiscriminately

Unless it is used to implement line joins, do not use parentheses in return statements or conditional statements. However, it is possible to use parentheses around tuples.

Yes:if foo:bar()while x:
x =bar()if x and y:bar()if not x:bar()return foo     for(x, y)in dict.items():...
No:if(x):bar()ifnot(x):bar()return(foo)

indentation##

Use 4 spaces to indent the code

Never use tabs, and do not mix tabs and spaces. For line concatenation, you should either align the line-wrapped elements vertically (see the example in the line length section), or use a hanging indent of 4 spaces (the first line at this time) There should be no parameters):

Yes:   # Aligned with opening delimiter
foo =long_function_name(var_one, var_two,
var_three, var_four)       # Aligned with opening delimiter in a dictionary
foo ={
long_dictionary_key: value1 +
value2,...}       # 4-space hanging indent; nothing on first line
foo =long_function_name(
var_one, var_two, var_three,
var_four)       # 4-space hanging indent in a dictionary
foo ={
long_dictionary_key:
long_dictionary_value,...}
No:    # Stuff on first line forbidden
foo =long_function_name(var_one, var_two,
var_three, var_four)      # 2-space hanging indent forbidden
foo =long_function_name(
var_one, var_two, var_three,
var_four)      # No hanging indent in a dictionary
foo ={
long_dictionary_key:
long_dictionary_value,...}

Empty line##

Two blank lines between top-level definitions, and one blank line between method definitions

There should be two blank lines between top-level definitions, such as function or class definitions. There should be a blank line between method definitions, class definitions and the first method. In the function or method, if you find some places in the function or method, you should leave a blank line.

Space##

Use the spaces on both sides of the punctuation in accordance with the standard typesetting conventions

There should be no spaces in the brackets.

Yes:spam(ham[1],{eggs:2},[])
No:spam( ham[1],{ eggs:2},[])

Do not put spaces before commas, semicolons, and colons, but you should add them after them (except at the end of the line).

Yes:if x ==4:         print x, y
x, y = y, x
No:if x ==4:         print x , y
x , y = y , x

No spaces should be added before the opening parenthesis of parameter lists, indexes or slices.

Yes:spam(1)
no:spam(1)
Yes: dict['key']= list[index]
No:  dict ['key']= list [index]

Add a space on both sides of binary operators, such as assignment (=), comparison (==, <, >, !=, <>, <=, >=, in, not in, is, is not), Boolean (and, or, not). As for how to use the spaces on both sides of arithmetic operators, you need to judge by yourself. But both sides must be consistent.

Yes: x ==1
No:  x<1

When'=' is used to indicate keyword parameters or default parameter values, do not use spaces on both sides.

Yes: def complex(real, imag=0.0):returnmagic(r=real, i=imag)
No:  def complex(real, imag =0.0):returnmagic(r = real, i = imag)

Do not use spaces to vertically align the marks between multiple lines, because this will become a maintenance burden (applicable to:, #, =, etc.):

Yes:
foo =1000  # comment
long_name =2  # comment that should not be aligneddictionary ={"foo":1,"long_name":2,}
No:
foo       =1000  # comment
long_name =2     # comment that should not be aligneddictionary ={"foo":1,"long_name":2,}

Shebang

Most .py files do not need to start with #!. According to PEP-394, the main file of the program should start with #!/usr/bin/python2 or #!/usr/bin/python3.

( Translator's Note: In computer science, Shebang (also known as Hashbang) is a string line (#!) consisting of a pound sign and an exclamation mark, which appears in the first two characters of the first line of a text file. In the file In the presence of Shebang, the program loader of the Unix-like operating system will analyze the contents of the Shebang, use these contents as an interpreter instruction, and call the instruction, and use the file path containing the Shebang as the parameter of the interpreter. For example, files beginning with the command #!/bin/sh will actually call the /bin/sh program when executed.)

#! It is first used to help the kernel find the Python interpreter, but it will be ignored when importing the module. Therefore, it is only necessary to add #!.

Comment##

Make sure to use the correct style for modules, functions, methods and inline comments

Docstring

Python has a unique way of commenting: using docstrings. A docstring is the first statement in a package, module, class, or function. These strings can be automatically extracted by the doc member of the object, and be pydoc Used. (You can run pydoc on your module and see what it looks like). Our convention for docstrings is to use triple double quotes """ (PEP-257 ). A docstring should Organize like this: First, a line of summary ending with a period, question mark or exclamation point (or the docstring is just one line). Then there is a blank line. Then there is the rest of the docstring, which should be the same The first quotation mark of a line is aligned. There are more docstring formatting specifications below.

Module

Each file should contain a license template. According to the license used by the project (for example, Apache 2.0, BSD, LGPL, GPL), select the appropriate template.

Functions and methods

The functions referred to below include functions, methods, and generators.

A function must have a docstring, unless it meets the following conditions:

Not visible from outside
Very short
easy to understand

The docstring should contain a detailed description of what the function does, as well as the input and output. Generally, it should not describe "how to do it", except for some complex algorithms. The docstring should provide enough information when someone else writes code to call the function At this time, he doesn't need to read a line of code, just look at the docstring. For complex code, adding comments next to the code makes more sense than using the docstring.

Several aspects of the function should be described in specific sections. These aspects are described below. Each section should start with a title line. The title line ends with a colon. Except for the title line, the rest of the section should be It is indented 2 spaces.

Args: List the name of each parameter, and use a colon and a space after the name to separate the description of the parameter. If the description is too long to exceed 80 characters on a single line, use a hanging indent of 2 or 4 spaces (and The rest of the file should be consistent). The description should include the required type and meaning. If a function accepts *foo (variable-length parameter list) or **bar (arbitrary keyword parameter), *foo and ** should be listed in detail bar.Returns: (or Yields: for generators) describes the type and semantics of the return value. If the function returns None, this part can be omitted. Raises: List all exceptions related to the interface.

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

class

The class should have a docstring under its definition to describe the class. If your class has public attributes (Attributes), then the document should have an Attributes section. And should follow the same format as the function parameters .

classSampleClass(object):"""Summary ofclasshere.   Longer classinformation....
 Longer classinformation....   Attributes:
  likes_spam: A boolean indicating if we like SPAM or not.
  eggs: An integer count of the eggs we have laid."""def __init__(self, likes_spam=False):"""Inits SampleClass with blah."""
self.likes_spam = likes_spam
self.eggs = 0def public_method(self):"""Performs operation blah."""

Block comments and line comments

The most need to write comments are those tricky parts of the code. If you have to explain during the next code review, then you should comment on it now. For complex operations, you should write a few before the operation begins. Line comments. For code that is not self-explanatory, a comment should be added at the end of the line.

# We use a weighted dictionary search to find out where i is in# the array.  We extrapolate position based on the largest num# in the array and the array size and then do binary search to# get the exact number.if i &(i-1)==0:        # true iff i is a power of2

To improve readability, comments should leave the code at least 2 spaces.

On the other hand, never describe the code. Assuming that the person reading the code understands Python better than you, he just doesn't know what your code does.

# BAD COMMENT: Now go through the b array and make sure whenever i occurs# the next element is i+1

class##

If a class does not inherit from other classes, it explicitly inherits from object. The same goes for nested classes.

Yes:classSampleClass(object):
passclass OuterClass(object):classInnerClass(object):
passclass ChildClass(ParentClass):"""Explicitly inherits from another class already."""
No:classSampleClass:
passclass OuterClass:classInnerClass:
pass

Inheriting from object is to make properties work properly, and to protect your code from a special potential incompatibility of PEP-3000. This also defines some special methods, These methods implement the default semantics of objects, including __new__, __init__, __delattr__, __getattribute__, __setattr__, __hash__, __repr__, and __str__.

String##

Even if the parameters are all strings, use the% operator or formatting method to format the string. But it cannot be generalized, you need to judge between + and %.

Yes: x = a + b
x ='%s, %s!'%(imperative, expletive)
x ='{}, {}!'.format(imperative, expletive)
x ='name: %s; score: %d'%(name, n)
x ='name: {}; score: {}'.format(name, n)
No: x ='%s%s'%(a, b)  # use +inthiscase
x ='{}{}'.format(a, b)  # use +inthiscase
x = imperative +', '+ expletive +'!'
x ='name: '+ name +'; score: '+str(n)

Avoid using the + and += operators in the loop to accumulate strings. Since strings are immutable, doing so will create unnecessary temporary objects and cause quadratic rather than linear runtimes. As an alternative, You can add each substring to the list, and then use .join to join the list after the loop ends. (You can also write each substring into a cStringIO.StringIO cache.)

Yes: items =['<table>']for last_name, first_name in employee_list:
items.append('<tr><td>%s, %s</td></tr>'%(last_name, first_name))
items.append('</table>')
employee_table =''.join(items)
No: employee_table ='<table>'for last_name, first_name in employee_list:
employee_table +='<tr><td>%s, %s</td></tr>'%(last_name, first_name)
employee_table +='</table>'

In the same file, keep the consistency of the use of string quotation marks. Use one of single quotation marks or double quotation marks to quote the string, and continue to use it in the same file. You can use another type of quotation mark in the string to Avoid using it in strings. GPyLint has added this check.

( Translator's Note: GPyLint is suspected to be a typo, it should be PyLint.)

Yes:Python('Why are you hiding your eyes?')Gollum("I'm scared of lint errors.")Narrator('"Good!" thought a happy Python reviewer.')
No:Python("Why are you hiding your eyes?")Gollum('The lint. It burns. It burns us.')Gollum("Always the great lint. Watching. Watching.")

Use triple double quotation marks """ instead of triple single quotation marks''' for multi-line strings. If and only if single quotes are used in the project to quote the string, it is possible to use triple ``' as a non-doc string The multi-line string is used to identify the reference. The docstring must use triple double quotation marks """. However, note that it is usually clearer to use implicit line concatenation, because multi-line strings are inconsistent with the indentation of other parts of the program.

Yes:print("This is much nicer.\n""Do it this way.\n")
No:      print """This is pretty ugly.
 Don't dothis."""

Files and sockets

At the end of the file and sockets, explicitly close it.

In addition to files, sockets or other file-like objects are opened when they are not necessary, and there are many side effects, such as:

  1. They may consume limited system resources, such as file descriptors. If these resources are not returned to the system in time after use, the code used to process these objects will exhaust the resources.
  2. Holding the file will prevent other operations such as moving and deleting the file.
  3. Just close the files and sockets logically, then they may still be read or write inadvertently by the shared program. Only when they are actually closed, they will run out of exceptions when they try to read or write. , And make the problem appear quickly.

Moreover, it is unrealistic to imagine that the file and sockets will be automatically closed when the file object is destroyed. Trying to bind the life cycle of the file object to the state of the file is unrealistic. Because of the following reasons:

  1. There is no way to ensure that the running environment will actually execute file destruction. Different Python implementations use different memory management techniques, such as delayed garbage processing mechanisms. Delayed garbage processing mechanisms may cause the object life cycle to be arbitrarily unlimited extend.
  2. Unexpected references to files can cause the holding time of the files to exceed expectations (for example, for abnormal tracking, including global variables, etc.).

It is recommended to use the "with" statement to manage files:

withopen("hello.txt")as hello_file:for line in hello_file:        print line

For file-like objects that do not support the use of the "with" statement, use contextlib.closing():

import contextlibwith contextlib.closing(urllib.urlopen("http://www.python.org/"))as front_page:for line in front_page:        print line

If the Python 2.5 code in Legacy AppEngine uses the "with" statement, you need to add "from future import with_statement".

TODO notes

Use TODO comments for temporary code, it is a short-term solution. Not perfect, but good enough.

TODO comments should contain the string "TODO" at all beginnings, followed by your name, email address or other identifier in parentheses. Then an optional colon. There must be a line of comment, explaining What to do. The main purpose is to have a unified TODO format so that those who add comments can search for it (and can provide more details as needed). Writing TODO comments does not guarantee that the person who writes will solve the problem himself. When You wrote a TODO, please write your name.

# TODO([email protected]): Use a "*" here for string repetition.# TODO(Zeke) Change this to use relations.

If your TODO is in the form of "doing something in the future", then make sure you include a specified date ("Resolved in November 2009") or a specific event ("Wait until all customers can process XML requests) Remove these codes").

Import format

Each import should be on its own line

Yes:import os     import sys
No:import os, sys

Imports should always be placed at the top of the file, after module comments and docstrings, and before module global variables and constants. Imports should be grouped in order from most common to least common:

  1. Standard library import
  2. Third-party library import
  3. Application specific import

In each grouping, it should be sorted lexicographically according to the complete package path of each module, ignoring case.

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

Statement##

Usually each statement should be on its own line

However, if the test result and the test statement fit on one line, you can also put them on the same line. If it is an if statement, you can only do this if there is no else. In particular, never do this with try/except Do, because try and except cannot be placed on the same line.

Yes:if foo:bar(foo)
No:if foo:bar(foo)else:baz(foo)try:bar(foo)  except ValueError:baz(foo)try:bar(foo)  except ValueError:baz(foo)

Access control

In Python, for trivial and less important access functions, you should directly use public variables to replace them, so as to avoid additional function call overhead. When adding more functions, you can use properties to maintain the syntax Consistency.

( Translator's Note: Object-oriented programmers who value encapsulation may be disgusted when they see this, because they have been educated: all member variables must be private! In fact, it is really a bit troublesome. Try to accept the Pythonic philosophy Bar)

On the other hand, if the access is more complicated, or the variable access overhead is significant, then you should use function calls like get_foo() and set_foo(). If the previous code behavior allows access via properties , Then do not bind the new access function to the property. In this way, any code that tries to access the variable through the old method will not run, and the user will realize that the complexity has changed.

Naming

module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_VAR_NAME, instance_var_name, function_parameter_name, local_var_name.

Names to avoid

Single-character names, except for counters and iterators.
Hyphen (-) in package/module name
Names that start and end with a double underscore (reserved by Python, such as init)

Naming convention

The so-called "Internal" means that it is only available in the module, or, protected or private in the class.
Start with a single underscore (_) to indicate that the module variable or function is protected (it will not be included when import * from is used).
Instance variables or methods beginning with a double underscore (__) indicate private in-class.
Put related classes and top-level functions in the same module. Unlike Java, there is no need to limit one class to one module.
Use uppercase words for class names (such as CapWords, Pascal style), but module names should be lowercase and underlined (such as lower_with_under.py). Although there are already many existing modules that use something like CapWords.py Naming, but it is now discouraged, because if the module name happens to be the same as the class name, it can be confusing.

Guidelines recommended by Guido, the father of Python

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 Constants CAPS_WITH_UNDER _CAPS_WITH_UNDER
Global/Class Variables lower_with_under _lower_with_under
Instance Variables lower_with_under _lower_with_under (protected) or __lower_with_under (private)
Method Names lower_with_under() _lower_with_under() (protected) or __lower_with_under() (private)
Function/Method Parameters lower_with_under
Local Variables lower_with_under

Main

Even a file intended to be used as a script should be importable. And a simple import should not cause the main functionality of the script to be executed, which is a side effect. The main function should be placed in a main () function.

In Python, pydoc and unit tests require modules to be importable. Your code should always check if __name__ ==&#39;__main__&#39; before executing the main program, so that the main program will not be imported when the module is imported carried out.

def main():...if __name__ =='__main__':main()

All top-level code is executed when the module is imported. Be careful not to call functions, create objects, or perform operations that should not be performed when using pydoc.

Source: Developer Technical Frontline
Developers are welcome to submit contributions
[ Free small secret circle qualification invites you to join](http://mp.weixin.qq.com/s?__biz=MzIyMjQ0MTU0NA==&mid=2247485122&idx=2&sn=5bd73f58ed7cc0243f63cced6e502344&chksm=e82c3fe5df5bb5ccee28d21d4bb4ascenefcha direct28221400eb3678)

Recommended Posts

Google Python Programming Style Guide
Python network programming
12. Network Programming in Python3
Detailed Python IO programming
Python GUI interface programming
Python Google Protocol Buffer
Talking about Python functional programming
Python programming Pycharm fast learning
Python3 script programming commonly used.md
Analysis of Python object-oriented programming
XTU programming Python training three
Black Hat Programming Application Python2
Black hat programming application of Python1
How to understand python object-oriented programming
Python classic programming questions: string replacement