📜 ⬆️ ⬇️

Google coding tips in Python. Part Two: Tips for Formatting Source Code


Good day. So the time has come for the publication of the second part of the translation of the style guide for the Python language from Google, so much liked by many habrovans, (the first part is carefully kept by the habr). Now we will touch directly on formatting source code in the Python programming language. As you know, cleanliness is a guarantee of health, and cleanliness of a program code is a guarantee of respect for colleagues and (ideally) encouragement from someone above. In general, Python itself is a well-read language, and even the syntax of this language calls for order in the code (and, as a result, in the head). But each of us is his own documenter and creator of his own design. And as it was already said once - it is impossible not to listen to the opinion of authoritative comrades. So, the second part of Google Python Style Guide - Python Style Rules is waiting for you under the cut. And pdf here as here.

Python Style Rules


Semicolons

Do not separate your lines with semicolons
Do not separate your lines with semicolons and do not use semicolons to separate commands that are on the same line.

Line length

The maximum string length is 80 characters.
Exceptions

  • Long import strings
  • URL in the comments

Do not use backslash as a newline. Use the explicit string concatenation available in Python through parentheses and curly braces. If necessary, you can add an extra pair of parentheses around the expression.

Good:

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'): 

')
When your text does not fit on one line, use parentheses to explicitly concatenate strings.

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

For comments, put the long URL, if necessary, on a single line.

Good:

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


Poorly:

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

Note the indent of the element in the line above (see the section on indents for clarification).

Parentheses

Use brackets sparingly
Do not use them (brackets) with a return statement or conditional if you do not need to arrange a line break. (See above). However, brackets are good to use for creating tuples.

Good:

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


Poorly:

 if (x): bar() if not(x): bar() return (foo) 


Indentation

Never use tabs or a mixture of tabs and spaces
In the case when you mean a line break, you must align each transferred item vertically as described in the example about the length of the lines, or using a space of 4 spaces, in this case there should not be any arguments on the first line.

Good:

 # Aligned with opening delimiter foo = long_function_name(var_one, var_two, var_three, var_four) # 4-space hanging indent; nothing on first line foo = long_function_name( var_one, var_two, var_three, var_four) 


Poorly:

 # 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) 


Blank lines

There should be two blank lines between top level declarations.
There should be two blank lines between top-level declarations, one blank line between method declarations. Two blank lines must be between top-level declarations, be it a class or a function. One blank line must be between the method definitions and between the class declaration and its first method. Use a single blank line as you like inside functions and methods.

Spaces

Follow standard typographical rules regarding the use of a space in punctuation.
No spaces inside any brackets.
The good: spam (ham [1], {eggs: 2}, [])
Bad: spam (ham [1], {eggs: 2}, [])

No spaces before comma, semicolon, or period. Use a space after a comma, a semicolon or a point, except when they are at the end of a line.

Good:

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

Poorly:

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

There are no spaces before the opening bracket, which starts the argument list, the index or the slice.
Good: spam (1)
Bad: spam (1)
Good: dict ['key'] = list [index]
Bad: dict ['key'] = list [index]
Surround binary operators with single spaces on each side, this applies to assignment ( = ), comparison operators ( ==, <,>,! =, <>, <=,> =, In, not in, is, is not ), and Boolean operators (and, or, not). Use as you think the environment
spaces with respect to arithmetic operators, but always arranging spaces on both sides of a binary operator will impart integrity to your code.
Good: x == 1
Bad: x <1
Do not use spaces on the sides of the "=" sign when you use it to point to a named argument or a default value.

Good:

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

Poorly:

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

Do not use spaces to vertically align pieces of consecutive lines, since such alignments are burdensome. (Refers to :, #, =, etc.):

Good:

 foo = 1000 # comment long_name = 2 # comment that should not be aligned dictionary = { 'foo': 1, 'long_name': 2, } 

Poorly:

  foo = 1000 # comment long_name = 2 # comment that should not be aligned dictionary = { 'foo' : 1, 'long_name': 2, } 


Line #! (hash bang)

Most .py files do not need to be run in line #!
Run the main program file using #! / Usr / bin / python . This string is used by the kernel to find the Python interpreter, but is ignored by Python when importing modules. This is necessary for a file that is executed directly.

Comments

Be sure to use the right style.
Be sure to use the correct style for a module, function, method, or string comment.

Lines of documentation.

Python has a unique commenting style - documentation lines. A documentation string is a string that is the first construct in a package, module, class, or function. Such strings can be exported automatically using the object attribute __doc__ and are used by pydoc. (Try running pydoc on your module to see what it looks like.) Our agreement on documentation strings tells you to use three double quotes to frame such a string. Documentation lines should be organized as a summary line (one physical line), broken down by character count, question mark or exclamation mark, following the empty line, and then the remaining documentation lines from the cursor position as the first quote of the first line. The following describes even more information on the design of documentation lines.

Modules

Each file must contain a license template. Select the appropriate license template for your project. (For example, Apache 2.0, BSD, LGPL, GPL).

Functions and methods

The term (function) used in this section refers to methods, functions, and generators.
The function must have a string of documentation in all cases except those described below:
  • Not visible outside the module
  • Very short
  • Obvious (easy to read)

The documentation string should give enough information to place a function call without reading its source code. The documentation string should describe the syntax of the function call and its semantics, but should not describe its implementation. For clever code, comments inside the source code are more preferable than documentation lines. Certain aspects of the function should be documented in the special sections listed below. Each section starts with a header line that ends with a period. Sections should be indented by two spaces, with the exception of the title.
Args :
List each parameter by name. The description should immediately follow the name and be separated by a dot and a space. If the description is too long to fit in 80 characters, use a hanging indent of 2 or 4 spaces (be consistent in the design of the entire file).
The description must refer to the type (s) required and the purpose of the argument. If the function allows * foo (variable-length argument lists) and / or ** bar (an arbitrary set of arguments of type key-value), they should be written as * foo and ** bar.
Returns : (or Yields for generators)
Describe the type and semantics of the return value. If the function always returns None, then this section is optional.
Raises :
List of all exceptions that are possible for this 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 


Classes

Classes must have a documentation line below their declaration. If your class has public attributes, they must be documented right there in the Attributes section and follow the same formatting style as the Args section.

 class SampleClass(object): """Summary of class here. Longer class information.... Longer class information.... 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 = 0 def public_method(self): """Performs operation blah.""" 


Blocks and inline comments


The last place that comments should have is tricky places in the code. If you want to explain them in your next code review, you should comment on them now. Complex operations that occupy several lines of documentation before its execution. Implicit parts should have a comment 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 of 2 


To improve readability, such comments should be at least 2 spaces away from the code. On the other hand, it is better not to describe the code at all. Assume that the person reading this code knows Python (and not what you tried to do) better than you.
 # BAD COMMENT: Now go through the b array and make sure whenever i occurs # the next element is i+1 


Classes

If a class is not inherited from any classes, explicitly inherit from the object class.
This also applies to nested classes.

Good:

 class SampleClass(object): pass class OuterClass(object): class InnerClass(object): pass class ChildClass(ParentClass): """Explicitly inherits from another class already.""" 


Poorly:

 class SampleClass: pass class OuterClass: class InnerClass: pass 


Inheritance from the object class is necessary to allow properties to work correctly and protects your code from possible incompatibility with Python 3000. It also defines special methods that implement the standard object semantics, for example: __new__, __init__, __delattr__, __getattribute__, __setattr__, __hash__ , __repr__, and __str__ .

Strings

Use the% operator to format strings
Use the% operator to format strings, even if all parameters are strings. Carefully consider using the + operator instead of the% operator.

Good:

 x = a + b x = '%s, %s!' % (imperative, expletive) x = 'name: %s; score: %d' % (name, n) 


Poorly:

 x = '%s%s' % (a, b) # use + in this case x = imperative + ', ' + expletive + '!' x = 'name: ' + name + '; score: ' + str(n) 

Avoid using the + and + = operators to concatenate a string using a loop, because strings are an immutable data type, this approach creates unnecessary objects and increases the time of work on a quadratic, rather than a linear law. Instead, simply add each substring to the list and use the join method after the loop ends (or write each substring to the cStringIO.StringIO buffer)

Good:

 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) 

Poorly:

 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>' 

Use “” ”for multi-line strings instead of“ ”. Note, however, that it is always better to use an explicit string concatenation, since multiline lines do not continue until the end of the program with the same indentation.

Good:

 print ("This is much nicer.\n" "Do it this way.\n") 

Poorly:

 print """This is pretty ugly. Don't do this. """ 


Files and Sockets

Explicitly close files and sockets when you finish working with them.
Neglecting open files, sockets, and other file-like objects has many side effects, such as:
  • They may consume limited system resources, such as file descriptors. Code that is associated with many objects can lead to the depletion of those resources without benefit if they are not returned to the system after use.
  • The content of files in open form may prevent other actions from being performed on them, such as, for example, moving or deleting.
  • Files and sockets that are publicly available through code may be inadvertently read or written after they have been logically “closed”.

If they are really closed, an attempt to read or write will throw an exception, thereby identifying the problem very quickly. Moreover, files and sockets are automatically closed when an object destructor is called, but associating the lifetime of an object with the state of the file is a bad practice for the following reasons:
  • There is no guarantee that the destructor of the object will be called during the execution of the program. Different Python implementations use different approaches to memory management, such as deferred garbage collection, which can significantly extend the life of a “remote” object.
  • Unexpected references to a file can make it “live” longer than we expect (for example, the stack of exceptions, global objects, etc.)
  • The priority way to manage files is to use the with construct.

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


Objects similar to the for loop that do not support the with construct and use contextlib.closing ()

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


Old code written under Python 2.5 can enable the use of the with construct using the " from __future__ import with_statement " import .

TODO Comment

Use the TODO comment for a time code, short-term patch, or a good, but not perfect solution.
TODO comments should include the TODO line at the beginning of each comment following the name, email address, or other identifier that can best provide a solution to the problem in brackets. Point is optional. A comment explaining what should happen there is not required. The main goal is a generic format for TODO, which allows you to quickly find a specific call that can provide a more detailed description of the problem. TODO is not a guarantee that a person will solve this problem. Thus, when you create a TODO, it almost always contains only your name.
 # TODO(kl@gmail.com): Use a "*" here for string repetition. # TODO(Zeke) Change this to use relations. If your TODO is of the form "At a future date do something" make sure that you either include a very specific date ("Fix by November 2009") or a very specific event ("Remove this code when all clients can handle XML responses."). 


Import clearance

Each import must be on a separate line.
Good:

 import os import sys 

Poorly:

 import os, sys 


Imports are always located at the beginning of the file, immediately after the module level comments, documentation lines, before declaring constants and
module level objects. Imports should be grouped in order from the simplest to the most complex:
  • Imports from the standard library
  • Third-party imports
  • Imports from your application libraries

Along with grouping, imports must be sorted lexicographically, nonregister-dependently, according to the full path to each module.
 import foo from foo import bar from foo.bar import baz from foo.bar import Quux from Foob import ar 


Constructions

Basically only one construction per line.
However, you can place the result of the text on the same line as the condition on you. But this can be done only in the case when the whole expression is placed on one line. In particular, you can never do this with the try / except construction, since try and except cannot be on the same line, and you can only place on one line with the if construct WITHOUT else.
Good:

 if foo: bar(foo) 


Poorly:

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


Access control

Hidden text
If the getter function would be simple, you would need to use shared variables for getter functions to avoid
additional resource costs for internal Python calls. When a lot of functionality is added, you can use properties
in order to follow the integrity of the interface. On the one hand, if the getter function is more complex, or the access speed to a variable is very important, you should use function calls (see the next section of the guideline), such as get_foo () and set_foo (). If the behavior allows access through the property, then do not attach a new getter to it. Any code that is still trying to access the variable using the old method should obviously fall, so that you can get a warning that the access complexity has changed.

Naming

module_name, package_name
module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_CONSTANT_NAME, global_var_name, instance_var_name, function_parameter_name, local_var_name.

Names to avoid:
  • Single-character names, excluding counters, or iterators
  • Cons in the names of modules and packages.
  • Double underscores (at the beginning and end of names) - reserved for the language.


Naming convention
  • “Internal” means internal for a module, protected or private class.
  • The leading underscore (_) substitution is supported for protected module variables and functions (which are not imported during import * from)
  • Substituting a double leading underscore (__) to the name of a variable or method effectively makes them private for this class (uses append to the name). Putting related classes and top-level levels together in a module. Unlike Java, you do not need to limit yourself to creating a single class in a single module.
  • Use camel notation for class naming, and notation with capital letters and underscores for module names. Although there are many modules that use camel notation for naming, but it is not recommended to do so, because it can be misleading, since The module is named after the class. (wait, didn’t I write import StringIO or from StringIO import StringIO?)


Styles are based on Guido's recommendations:
Type ofExternalInterior
Packageslower_with_under
Moduleslower_with_under_lower_with_under
ClassesCapwords_CapWords
ExceptionsCapwords
Functionslower_with_under ()_lower_with_under ()
Global / Interclass ConstantsCAPS_WITH_UNDER_CAPS_WITH_UNDER
Global / Interclass Variableslower_with_under_lower_with_under
Class instance variableslower_with_under_lower_with_under (protected) or __lower_with_under (private)
Method Nameslower_with_under ()_lower_with_under () (protected) or __lower_with_under () (private)
Function / Method Argumentslower_with_under
Local variableslower_with_under


Main

Even when the file was created in order to be imported ..
Even when the file was created in order to be imported, a regular import should not have side effects in the form of the execution of the functional part of the script. The main functionality should be incorporated in the main () function.
In Python, pychecker, pydoc and unit tests, imported modules are required. Your code should always check if __name__ == '__main__' before execution, which means that your module will not be fully executed when importing it into another program.
 def main(): ... if __name__ == '__main__': main() 

All top level code will be executed when the module is imported. Be careful not to call functions, do not create an object, and do not perform any other type of operation that should not be performed when the file is checked with pychecker or documentation is being collected with pydoc.

Final words

Hidden text
If you are editing someone's code, select a few minutes to look at this code and choose the style of writing. If each operator is framed by spaces, you should do the same. , (#) , . , , , .
, , . , — , . .

Version: 2.48
Amit Patel
Antoine Picard
Eugene Jhong
Jeremy Hylton
Matt Smart
Mike Shields


From translator


FAQ


Thanks

Thank you so much squaii for the review and search for errors.

Conclusion

Please, I implore you - write a decent code, gentlemen! Take care of those who will support your work. Pity their eyes, save their strength, give them the joy of life, free from constantly sick head and circles under the eyes. As you know, you have just written the code and after a month you returned to support it - you are already in team development, so do not be lazy to write transparently even when you intend to support the written code alone. Eradicate evil, violence and sodomy among IT-specialists (and not only). All good!

PS: And remember:

Source: https://habr.com/ru/post/180509/


All Articles