Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand the Python code style inside Google

2025-02-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article is to share with you about how to understand the Python code style within Google. The editor thinks it is very practical, so I share it with you. I hope you can get something after reading this article.

1 background

Python is the dynamic language mainly used by Google. This style guide lists what you should and shouldn't do when programming with Python (dos & don'ts).

To help you organize your code correctly, we have written a Vim settings file. For Emacs, the default setting is fine.

Many teams use yapf automatic formatting tools to avoid format disputes

2 Python language Rule 2.1 Lint

Use pylint with code

2.1.1Definition (translated as definition below)

Pylint is a tool for finding bug and code style problems in Python code. Pylint looks for problems that are often caught in compilers in non-dynamic languages such as C or C++. Because Python is a dynamic language, some warnings may be incorrect, but there should be very few error warnings.

2.1.2 Pros

Can find some errors that are easy to be missed, such as spelling mistakes, calls earlier than declarations, and so on.

2.1.3 Cons

Pylint is not perfect. In order to make better use of tools, we sometimes need

A. Write around it (adapted to context style)

b. Suppress some warnings

c. Optimization tool

2.1.4 Decision (translated as suggestions below)

Ensure that pylint is applied to the code

If some warnings are inappropriate, suppress them so that other warnings are not hidden. To suppress warnings, you can set comments at the line level:

Dict = 'something awful' # Bad Idea... Pylint: disable=redefined-builtin

Pylint warnings contain identification names (empty-docstring), and Google proprietary warnings begin with g -.

If the reason for suppressing the warning is not clear enough in the identity name, please add additional comments.

The advantage of suppressing warnings in this way is that we can simply find suppressed warnings and revisit them.

You can get a list of pylint warnings in the following ways:

Pylint-list-msgs

Get more specific information about a particular message in the following ways:

Pylint-help-msg=C6409

Give priority to using pylint: disable over the old method (pylint: disable-msg) if you want to suppress warnings due to unused parameters, you can del at the beginning of the function and note why you want to delete these unused arguments. Just a "unused" is not enough:

Def viking_cafe_order (spam, beans, eggs=None):

Del beans, eggs # Unused by vikings.

Return spam + spam + spa

Other ways to suppress warnings include using'_'as the identification of unused parameters, adding 'unused_',' before the parameter name, or assigning these parameters to'_'. These methods are OK, but they are no longer encouraged. The first two methods affect the way the parameter is passed through the parameter name, while the last one does not guarantee that the parameter is not used.

2.2 Imports

Use import only for import packages and modules, not for separate classes or functions. (this is a special surprise for typing_module.)

2.2.1 definition

A reusability mechanism for sharing code from one module to another

2.2.2 Pros

The namespace management convention is simple, and the source of each identity is consistently specified. For example, x.Obj indicates that Obj is defined in module x

2.2.3 Cons

Module names may conflict, and some module names may be long and inconvenient

2.2.4 it is recommended that import x (when x is a package or module) from x import y (when x is a package prefix, y is a module name without a prefix) from x import y as z (when there is a duplicate module name y or y is too long for reference) import y as z (use such as import numpy as np only in very general abbreviations)

Take sound.effects.echo as an example:

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

Do not use relative references, even within the same package, use the full package name import, which helps avoid inadvertently repeating import packages.

The above rules do not apply from typing module and six.moves module import

2.3 package

Each module has to import from the full path

2.3.1 Pros

It can avoid module name conflicts and misreferences caused by module search paths that do not match the author's expectations. Make it easier to find modules.

2.3.2 Cons

It's a bit difficult to deploy code because the package architecture also requires assignments, but for the current deployment mechanism, this is not a problem.

2.3.3 recommendations

All new code needs to import the module from the full package name

The import example should look like this:

Yes:

# Reference absl.flags in code with the complete name (verbose).

# call absl.flags with the full path in the code

Import absl.flagsfrom doctor.who import jodie

FLAGS = absl.flags.FLAGS

# Reference flags in code with just the module name (common).

# only use the package name to call flags in the code

From absl import flagsfrom doctor.who import jodie

FLAGS = flags.FLAGS

No: (assuming the file is in doctor/who and jodie.py is here)

# Unclear what module the author wanted and what will be imported. The actual

# import behavior depends on external factors controlling sys.path.

# Which possible jodie module did the author intend to import?

# it is not clear which package the author wants and which package is the final import

# actual import operations depend on sys.path controlled by external parameters

# so which possible jodie module does the author want to import?

Import jodie

You should not assume that the path where the main code is located is included in the sys.path, even though sometimes you can work. In the previous example code, we should assume that import jodie refers to import, a third-party package called jodie, or jodie in the top-level directory, rather than a jodie.py of the current path

2.4 exception

Exception handling is allowed, but it must be used with caution

2.4.1 definition

An exception is a means of jumping out of the control flow of a normal code snippet to handle errors or other exception conditions.

2.4.2 Pros

The control flow of normal code will not be affected by error handling code. Exception handling also allows the control flow to skip multiple pieces of code in some cases, such as returning results from N embedded functions at a step rather than forcibly continuing the error code.

2.4.3 Cons

It may make the control flow difficult to understand, and it is easier to miss the error report of calling library functions.

2.4.4 recommendation

Exceptions must follow specific conditions:

Use raise MyError ('Error message') or raise MyError (), not two-segment raise MyError,' Error message' when the built-in exception class makes sense, try to use the built-in exception. For example, a ValueError is thrown to indicate that a program error occurs that seems to violate a preset premise (such as passing a negative number to a positive number).

Do not use assert to fragment common structure parameter values. Assert is used to confirm the correctness of internal calculations and is not used to indicate the occurrence of unexpected events. If the exception is required by subsequent processing, use the raise statement to handle it, for example:

Yes:

Def connect_to_next_port (self, minimum):

"" Connects to the next available port.

Args:

Minimum: A port value greater or equal to 1024.

Returns:

The new minimum port.

Raises:

ConnectionError: If no available port is found.

"

If minimum

< 1024: # Note that this raising of ValueError is not mentioned in the doc # string's "Raises:" section because it is not appropriate to # guarantee this specific behavioral reaction to API misuse. # 注意抛出ValueError这件事是不在docstring中的Raises中提及, 因为这样并适合保障对于API误用的特殊反馈 raise ValueError('Minimum port must be at least 1024, not %d.' % (minimum,)) port = self._find_next_open_port(minimum) if not port: raise ConnectionError('Could not connect to service on %d or higher.' % (minimum,)) assert port >

= minimum, 'Unexpected port% d when minimum was% d.'% (port, minimum)

Return port

No:

Def connect_to_next_port (self, minimum):

"" Connects to the next available port.

Args:

Minimum: A port value greater or equal to 1024.

Returns:

The new minimum port.

"

Assert minimum > = 1024, 'Minimum port must be at least 1024.'

Port = self._find_next_open_port (minimum)

Assert port is not None

Return port

Libraries or packages may define their own exceptions. When doing so, an existing exception class must be inherited, the name of the exception class should end with Error, and foo.FooError should not be introduced.

Never use an except: statement that catches all exceptions, or catch Exception or StandardError unless:

Python is highly tolerant in this respect, and except: statements catch including spelling errors, sys.exit (), Ctrl+C terminations, unit test failures, and all other exceptions you didn't expect to catch.

Throwing this exception again creates an isolated point in the program where the exception will not continue but will be logged and eliminated (for example, by protecting the outermost layer to protect the thread from crashing).

The amount of code inside the most concise try/except expression. The larger the code in the try code block, the month may throw an exception in the code where you do not want to throw an exception. In this case, try/except masks a real exception.

Use finally to execute code, which is executed regardless of whether or not an exception is thrown in the try block. This is very useful when cleaning up (that is, closing files).

When an exception is caught, segment it with as instead of a comma.

Try:

Raise Error ()

Except Error as error:

Pass

2.5 Global variables

Avoid global variables

2.5.1 definition

Variables declared at the module level or as class attributes

2.5.2 Pros

Sometimes it works.

2.5.3 Cons

During the import process, it is possible to change the module behavior because global variables are declared during the first introduction of the module

2.5.4 recommendation

Avoid global variables

As a technical variable, module-level constants are allowed and encouraged. For example, MAX_HOLY_HANDGRENADE_COUNT = 3, the constant must consist of uppercase letters and underscores, see the naming rules below

If necessary, global variables need to be declared at the module level and privatized within the module by adding _ to the variable name. External access to module global variables must be through common module-level functions, see naming rules below

2.6 embedded / local / inner classes and functions

Embedded local functions or classes can be used to turn off local variables. Internal class consciousness is available. My understanding here is that when an embedded local function or class is in the same closed scope as a local variable.

2.6.1 definition

Classes can be defined within methods, functions, and classes. A function can be defined within a method or function. Embedded functions have read-only access to closed-scope variables.

2.6.2 Pros

Allows you to define utility classes or utility functions that are only available in a very limited scope. Very ADT-y (?? Meets the requirements of abstract data types and is commonly used to implement decorators

2.6.3 Cons

Instances of embedded or local classes cannot be pickle, and embedded functions or classes cannot be tested directly. Nesting makes external functions longer and harder to read.

2.6.4 recommendations

Except for some special declarations, these embedded / local / inner classes and functions are OK. Avoid embedded functions or classes except when you need to turn off a local value. The translator may understand that except in the case of enclosing local variables in the same scope. Do not convert a function to an embedded instruction in order to avoid access. In this case, place the function at the module level and precede the function name with _ to ensure that the test can access the function.

2.7 list derivation and generator expressions

Is available in simple cases

2.7.1 definition

List, Dict and Set derive generators and generator expressions provide a concise and efficient way to generate containers and iterators without the need for traditional loop, map (), filter () or lambda expressions

2.7.2 Pros

Simple derivation and expression is more concise and clear than other dictionary, list or set generation methods. Generator expressions can be efficient because generating lists is completely avoided.

2.7.3 Cons

The derivation expression or generator expression of the load is difficult to read.

2.7.4 recommendation

It can be used in simple cases. Each part (mapping expression, filter expression, etc.) should be completed on one line. Multiple for terms or filter expressions are not allowed. Use loops when the situation becomes complex and appropriate.

Yes:

Result = [mapping_expr for value in iterable if filter_expr]

Result = [{'key': value} for value in iterable

If a_long_filter__expression (value)]

Result = [complicated_transform (x)

For x in iterable if predicate (x)]

Descriptive_name = [

Transform ({'key': key,' value': value}, color='black')

For key, value in generate_iterable (some_input)

If complicated_condition_is_met (key, value)

]

Result = []

For x in range (10):

For y in range (5):

If x * y > 10:

Result.append (x, y))

Return {x: complicated_transform (x)

For x in long_generator_function (parameter)

If x is not None}

Squares_generator = (xylene 2 for x in range (10))

Unique_names = {user.name for user in users if user is not None}

Eat (jelly_bean for jelly_bean in jelly_beans

If jelly_bean.color = = 'black')

No:

Result = [complicated_transform (

X, some_argument=x+1)

For x in iterable if predicate (x)]

Result = [(x, y) for x in range (10) for y in range (5) if x * y > 10]

Return ((x, y, z)

For x in range (5)

For y in range (5)

If x! = y

For z in range (5)

If y! = z)

2.8 default iterators and operators

Use them for types such as lists, dictionaries, and files that support default iterators and cloud algorithms

2.8.1 definition

Container types (such as dictionaries, lists, etc.) define default iterators and member checking operators.

Pros

Default iterators and operators are simple and efficient, and can express operations directly without additional method calls. Functions that use the default operator are generic. Can be used for any type that supports these operations.

Cons

You can't tell a type by a method name, for example, has_key () means a dictionary, which is an advantage.

Suggestion

Use default iterators and operators for supported types such as lists, dictionaries, and files. Built-in types also define iterator methods. Give priority to these methods over those that return the list. Unless you can be sure that the container will not be changed during traversal. Do not use Python 2 proprietary iterative methods unless necessary.

Yes:

For key in adict:...

If key not in adict:...

If obj in alist:...

For line in afile:...

For k, v in adict.items ():...

For k, v in six.iteritems (adict):...

No:

For key in adict.keys ():...

If not adict.has_key (key):...

For line in afile.readlines ():...

For k, v in dict.iteritems ():...

2.9 Generator

Use the generator when needed

2.9.1 definition

The generator function returns an iterator that generates a value each time a yield statement is executed. After generating a value, the generator function is suspended until the next value is needed.

2.9.2 Pros

Simplify the code because local variables and control flows are retained at each call, and the generator saves more memory than generating an entire list value at once.

2.9.3 Cons

None

2.9.4 recommendation

Recommended use. Use "Yields:" instead of "Returns:" in the document string of the generator function

2.10 Lambda expression

A single line of code is fine.

2.10.1 definition

Lambda defines anonymous functions in an expression, not in a statement. Lambda expressions are often used to define callback functions or operators used by higher-order functions such as map () and filter ().

2.10.2 Pros

Convenient

2.10.3 Cons

It is harder to read and debug than local functions, and anonymity means stack traces are harder to understand. Expressiveness is limited because the lambda function contains only one expression

2.10.4 recommendation

For a single line of code, you can use lambda expressions. If the code in the lambda expression is more than 60-80 characters, it is best to define it as a regular embedded function.

For general operations such as multiplication, use operator module built-in functions instead of redefining anonymous functions, for example, using operator.mul instead of lambda XMagi y: X * y

2.11 conditional expression

It can be used in simple cases.

2.11.1 definition

Conditional expressions, also known as ternary operators, are a shorter alternative to if statements. For example, x = 1 if cond else 2

2.11.2 Pros

Shorter and more convenient than if statements

2.11.3 Cons

It may be more difficult to read than if statements, and the conditional part may be difficult to locate when the expression is long.

2.11.4 recommendations

Simple cases can be used. Each part (truth expression, if expression, else expression) must be completed on one line. Use the full if statement if you are rich with conditional expressions.

Yes:

One_line = 'yes' if predicate (value) else' no'

Slightly_split = ('yes' if predicate (value))

Else'no, nein, nyet')

The_longest_ternary_style_that_can_be_done = (

'yes, true, affirmative, confirmed, correct'

If predicate (value)

Else'no, false, negative, nay')

No:

Bad_line_breaking = ('yes' if predicate (value) else)

'no') portion_too_long = (' yes'

If some_long_module.some_long_predicate_function (

Really_long_variable_name)

Else'no, false, negative, nay')

2.12 default parameter valu

OK in most cases

2.12.1 definition

You can set a value for a variable at the end of the function argument list, such as def foo (a, bread0):. If foo passes in only one parameter when calling, then the b variable is set to 0, and if two arguments are passed in during the call, b is assigned the second parameter value.

2.12.2 Pros

Usually a function may have a large number of default values, but there are few times when you need to modify these default values. The default value provides a simple way to satisfy the above situation without having to redefine many functions for these rare cases. Because Python does not support overloading methods or functions, the default parameter is an easy way to "fake overload" behavior.

2.12.3 Cons

The default parameters are copied when the module is loaded. This causes problems when the parameter is a mutable object, such as a list or dictionary. If the function modifies these mutable objects (such as adding elements to the end of the list). The default value is changed.

2.12.4 recommendation

Please pay attention to the following warning when using it-do not use mutable objects as default values when defining functions or methods.

Yes:

Def foo (a, b=None):

If b is None:

B = []

Def foo (a, b: Optional [Sequence] = None):

If b is None:

B = []

Def foo (a, b: Sequence = ()): # Empty tuple OK since tuples are immutable empty tuples are also immutable

...

No:

Def foo (a, b = []):

...

Def foo (a, b=time.time ()): # The time the module was loaded??? When the module was loaded?

...

Def foo (a, b=FLAGS.my_thing): # sys.argv has not yet been parsed... Sys.argv has not been parsed yet

...

Def foo (a, b: Mapping = {}): # Could still get passed to unchecked code can still pass in unchecked code (translation may be incorrect here)

...

2.13 attributes

Using properties, you can access or set data through simple and lightweight accessor and setter methods.

2.13.1 definition

A way in which a decorator is called to obtain and set a property as a standard property access when calculating a lightweight.

2.13.2 Pros

For simple property access, reducing explicit get and set methods can improve readability. Lazy computing is allowed. It is considered to be a Python way to maintain class interfaces. In performance, attributes are allowed to bypass the required trivial access methods when direct access to variables is more reasonable.

2.13.3 Cons

Must inherit from object in Python2, which may hide side effects such as operator overloading. For subclasses, attributes can be confusing.

2.13.4 recommendation

Use attributes to access or set data in new code that usually has simple and lightweight access and setting methods. Properties are decorated with @ property when created, and participate in the decorator

If the attribute itself is not overridden, the inheritance with the attribute may not be clear enough, so it is necessary to ensure that the access method is accessed indirectly to ensure that the method overload of the subclass is called by the attribute (using Template Method DP, translator: it should be the template method design pattern).

Yes:

Class Square (object):

A square with two properties: a writable area and a read-only perimeter.

To use:

> sq = Square (3)

> sq.area

nine

> sq.perimeter

twelve

> sq.area = 16

> sq.side

four

> sq.perimeter

sixteen

"

Def _ _ init__ (self, side):

Self.side = side

@ property

Def area (self):

"Area of the square."

Return self._get_area ()

@ area.setter

Def area (self, area):

Return self._set_area (area)

Def _ get_area (self):

"" Indirect accessor to calculate the 'area' property. ""

Return self.side * * 2

Def _ set_area (self, area):

"" Indirect setter to set the 'area' property. ""

Self.side = math.sqrt (area)

@ property

Def perimeter (self):

Return self.side * 4

2.14 True/False expression

Whenever possible, use the if statement of implicit False

2.14.1 definition

In a Boolean environment, Python determines that some values are False. A quick empirical rule is that all "null" values are considered False, so the Boolean values of 0, None, [], {},''are all False.

2.14.2 Pros

Conditional statements that use Python Boolean types are more readable and harder to make mistakes, and in most cases faster.

2.14.3 Cons

It may be a little strange for the developers of Cpicket +.

Suggestion

If possible, use implicit False. For example, using if foo: instead of if foo! = []: here are some warnings you should keep in mind:

Use if foo is None (or if foo is not None) to check None. For example, when checking whether a variable or parameter with a default value of None is assigned another value, the Boolean value of the other values assigned may be False. Do not use = = to compare with variables with a Boolean value of False, use if not x, if you need to distinguish between False and None, then use chained expressions such as if not x and x is not None for sequences (such as strings, lists, tuples), using the fact that the empty order is listed as False, so use if seq: and if not seq: instead of if len (seq) or if not len (seq):. Implicit False may introduce more risks when dealing with integers (for example, accidentally doing the same for None and 0) you can compare the integer 0 with a value that is known to be an integer (and not the result of len ()).

Yes:

If not users:

Print ('no users')

If foo = = 0:

Self.handle_zero ()

If I% 10 = 0:

Self.handle_multiple_of_ten ()

Def f (x=None):

If x is None:

X = []

No:

If len (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 ()

Def f (x=None):

X = x or []

2.15 language features of abandonment

Use string methods instead of string modules whenever possible. Use function call syntax instead of apply. Use lists to derive expressions and for loops instead of filter and map when the function argument is already an inline anonymous function

2.15.1 definition

The current version of Python provides a generally preferred way to build.

2.15.2 recommendation

We don't use any version of Python that doesn't support these features, so there's no reason not to use the new approach.

Yes:

Words = foo.split (':')

[X [1] for x in my_list if x [2] = = 5]

Map (math.sqrt, data) # Ok. No inlined lambda expression. Yes, there are no inline lambda expressions

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)

2.16 lexical scope

Can be used

2.16.1 definition

An embedded Python function can reference variables defined in the closure namespace, but cannot copy them. Variable binding is resolved to use lexical scope, that is, based on static program text. Any assignment to a name within a block causes Python to use a reference to that name as a local variable, even if it is used before the assignment. If there is a global declaration, the name is considered a global variable.

An example of using this feature is:

Def get_adder (summand1):

"Returns a function that adds numbers to a given number."

Def adder (summand2):

Return summand1 + summand2

Return adder

2.16.2 Pros

It often makes the code more concise and elegant, especially for experienced Lisp and Scheme (as well as Haskell and ML and others) programs.

2.16.3 Cons

It can lead to confusing bug, such as this PEP-0227-based example.

I = 4

Def foo (x):

Def bar ():

Print (I, end='')

#...

# A bunch of code here

#...

For i in x: # Ah, I * is* local to foo, so this is what bar sees i are local variables to foo, so here is the value obtained by the bar function

Print (I, end='')

Bar ()

So foo ([1, 2, 3]) prints 1 2 3 3 3 instead of 1 2 3 4.

2.16.4 recommendation

Can be used

2.17 function and method decorator

When there are obvious benefits, use it carefully and wisely, avoid @ staticmethod, and control the use of @ classmethod

2.17.1 definition

Function and method decorators (that is, @ tokens). A common decorator is @ property, which converts common methods into dynamically calculated properties. However, the decorator syntax also allows the user to define the decorator, especially for some functions my_decorator:

Class C (object):

@ my_decorator

Def method (self):

# method body...

Is equivalent to

Class C (object):

Def method (self):

# method body...

Method = my_decorator (method)

2.17.2 Pros

Be able to gracefully transform the method, which may reduce some repetitive code and remain invariant, and so on.

2.17.3 Cons

The decorator can operate arbitrarily on the parameters and return values of the function, resulting in very invisible operation behavior. In addition, the decorator is executed during import, and the effectiveness of the decorator code can be very difficult to recover.

2.17.4 recommendation

Use decorators cautiously where there are obvious benefits. Decorators should follow the same import and naming guidelines as functions. The decorator's documentation should clearly declare the function as the decorator function. And write unit tests for decorator functions.

Avoid external dependencies on the decorator itself (e.g., do not rely on files, socket, database connections, etc.), because these external dependencies may not be available while the decorator is running (in import, possibly from pydoc or other tools). A decorator that is passed in valid parameters and called should be (as far as possible) available in all cases.

The decorator is a special "top-level code", see main

Never use @ staticmethod unless you have to integrate an API into an existing library and write a module-level function.

Use @ classmethod. Only when writing a named constructor or a class-specific process that modifies the necessary global state (such as process cache, etc.).

2.18 thread

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

Although Python built-in data types such as dictionaries and so on seem to have atomic operations, there are rare cases where they are non-atomic (for example, if _ _ hash__ or _ _ eq__ are implemented as Python methods), they should not rely on these types of atomicity. Nor should it rely on atomic variable assignments (because it depends on dictionaries)

Priority is given to the Queue class of the Queue module as a way to communicate data between threads. In addition, if you use the threading module and its locking primitives (lock primitive). Understand the rational use of conditional variables to facilitate the use of threading.Condition rather than lower-level locks.

2.19 overly powerful features

Avoid using as much as possible

2.19.1 definition

Python is a very flexible language and provides many novel features, such as custom metaclass, access bytecode, dynamic compilation, dynamic inheritance, object parent class redefinition, import hacks, reflection (for example, some applications for getattr ()), system built-in modifications and so on.

2.19.2 Pros

These are very powerful language features that can make programs more compact.

2.19.3 Cons

It is tempting to use these new features. But they are not absolutely necessary. They are difficult to read and understand. It is also difficult to debug code that uses unusual features at the bottom. This may not be the case for the original author, but looking at the code again may be more difficult than longer but more straightforward code.

2.19.4 definition

Avoid using these features in your code.

Standard libraries and classes that use these features internally are available (for example, abc.ABCMeta,collections.namedtuple, and enum)

2.20 new version of Python: Python3 and slave _ _ future__import

Python3 is already available, although not every project is ready to use Python3, all code should be compatible with Python3 and tested in a Python3 environment if possible.

2.20.1 definition

Python3 is a major change for Python, and although existing code is usually written in Python2.7, there are simple things that can be done to make the code express its intentions more clearly, so that the code can better run under Python3 without adjustment.

2.20.2 Pros

Consider that the code written by Python3 is clearer and easier to run in a Python3 environment once all the dependencies are in place.

2.20.3 Cons

Some people will think that the default template is ugly and that features that import doesn't actually need are not common in modules.

2.20.4 recommendation

From future imports

Encourage the use of the from _ _ future__ import statement. All new code should contain the following code, and existing code should be updated to be as compatible as possible:

From _ _ future__ import absolute_import

From _ _ future__ import division

From _ _ future__ import print_function

If you are not familiar with these, read these in detail: absolute import, new / division behavior, and print function

Do not omit or remove these import, even if they are not in use in the module, unless the code is only used for Python3. It is best to always have an import from future in all documents to ensure that it will not be forgotten when someone uses it for subsequent editing.

There are other from _ _ future__import statements, depending on your preference. Our proposal does not include unicode_literals because it has no obvious advantage, because the implicit default transcoding has led to its introduction in many places within Python2.7, and when necessary, most code is best expressed explicitly using breads' and u''btyes and unicode strings.

The six, future, or past libraries

When the project needs to support Python2 and 3, use six,future and past.

2.21 Code with type comments

Python3 code can be type annotated according to PEP-484, and type checking tools such as pytype can be used for type checking during build.

Type comments can be in source code or in stub pyi file. Whenever possible, comments should be written in the source code. Use pyi files for third parties or extension modules.

2.21.1 definition

Type comments (also known as "type hints") are used for function or method parameters and return values:

Def func (a: int)-> List [int]:

You can also declare the type of the variable with a separate comment:

A = SomeFunc () # type: SomeType

2.21.2 Pros

Type comments improve the readability and maintainability of code, type checking turns many run errors into build errors, and reduces the ability to use overly powerful features.

2.21.3 Cons

Type declarations need to be constantly updated, and the use of type checking may reduce the ability to use overly powerful features for code that is considered valid.

2.21.4 recommendation

Python type analysis is strongly encouraged when updating the code. When making additions and modifications to the public API, include the python type declaration and check through the pytype in the build system. Static type checking is relatively new to Python, and we admit that some unintended side effects (such as incorrectly inferred types) may reject the use of some items. In this case, the author is encouraged to add a link to the BUILD file or in the code with TODO or type comments to the bug description that are not currently searched.

3 Python code style specification 3.1 semicolon

Do not add a semicolon at the end of a line, and do not merge two lines of statements into one line with a semicolon

3.2 Line length

The maximum line length is 80 characters

An explicit exception that exceeds 80 characters:

In long import comments: URL, path, flags, etc. Module-level long string constants pylint that do not contain spaces and are not convenient for splitting are used for diable comments (such as # pylint: disable=invalid-name)

Do not use backslash connections except for context manager with statements that require three or more layers

Use Python's implicit line joining inside parentheses, brackets and braces (implicit line join method-parenthesis join, including (), [], {}). If necessary, you can also add an extra pair of parentheses to the expression.

Yes:

Foo_bar (self, width, height, color='black', design=None, Xerox Foo'

Emphasis=None, highlight=0)

If (width = = 0 and height = = 0 and

Color = 'red' and emphasis = =' strong'):

When a string cannot be completed in one line, use parentheses to implicitly concatenate lines:

X = ('This will build a very long long'

'long long long long long long string')

Within the comment, if necessary, put the long URL on its own 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

When defining a with statement with more than three lines of expression, you can use a backslash to break the line. For two-line expressions, use nested with statements:

Yes:

With very_long_first_expression_function () as spam,\

Very_long_second_expression_function () as beans,\

Third_thing () as eggs:

Place_order (eggs, beans, spam, beans)

With very_long_first_expression_function () as spam:

With very_long_second_expression_function () as beans:

Place_order (beans, spam)

No:

With VeryLongFirstExpressionFunction () as spam,\

VeryLongSecondExpressionFunction () as beans:

PlaceOrder (eggs, beans, spam, beans)

Note the indentation in the above example, see indentation for details

When other lines exceed 80 characters, and the yapf automatic formatting tool cannot make the branches meet the requirements, it is allowed to exceed the 80 character limit.

3.3 brackets

Reasonable use of parentheses

Although not necessary, you can add parentheses to the tuple. Do not use parentheses in return statements or conditional statements, except for implicit join rows or tuples.

Yes:

If foo:

Bar ()

While x:

X = bar ()

If x and y:

Bar ()

If not x:

Bar ()

# For a 1 item tuple the () s are more visually obvious than the comma.

Onesie = (foo,)

Return foo

Return spam, beans

Return (spam, beans)

For (x, y) in dict.items ():...

No:

If (x):

Bar ()

If not (x):

Bar ()

Return (foo)

3.4 indent

Indent with 4 spaces

Do not use tabs in indented code snippets, or mix tabs and spaces. If you join multiple lines, the lines should be aligned vertically or indented again with 4 spaces (in this case there should be no code after the first line parentheses).

Yes:

# Aligned with opening delimiter

# is aligned with opening delimiter (the translator understands it as the entrance to the delimiter, such as three parentheses, string quotation marks, etc.)

Foo = long_function_name (var_one, var_two

Var_three, var_four)

Meal = (spam

Beans)

# Aligned with opening delimiter in a dictionary

Foo = {

Long_dictionary_key: value1 +

Value2

...

}

# 4-space hanging indent; nothing on first line

# indent 4 spaces with no content after parentheses on the first line

Foo = long_function_name (

Var_one, var_two, var_three

Var_four)

Meal = (

Spam

Beans)

# 4-space hanging indent in a dictionary

Foo = {

Long_dictionary_key:

Long_dictionary_value

...

}

No:

# Stuff on first line forbidden

# content is not allowed on the first line

Foo = long_function_name (var_one, var_two

Var_three, var_four)

Meal = (spam

Beans)

# 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

...

}

3.4.1 about trailing commas

With regard to the trailing comma in a sequence of elements, it is recommended only when the container end symbol],) or} is not on the same line as the last element. The presence of the trailing comma is also used as a hint for our Python code automatic formatting tool yapf to automatically adjust the container element to one element per line when it appears after the last element.

Yes:

Golomb3 = [0,1,3]

Golomb4 = [

0

one,

four,

six,

]

No:

Golomb4 = [

0

one,

four,

six

]

3.5 blank lines

Interval two lines between the top-level definitions (functions or classes). There should be a blank line between the definition of the method and between the line of the class and the first method. There is no blank line after the def line. You can use a single blank line within the function or method where you think it is appropriate.

3.6 Spac

Follow the standard space and punctuation typesetting rules.

No extra spaces inside parentheses (), [], {}.

Yes:

Spam (ham [1], {eggs: 2}, [])

No:

Spam (ham [1], {eggs: 2}, [])

Do not use spaces before commas, semicolons, and colons, but add spaces after them, unless 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 are added before the parentheses of the function call and the parentheses of the index slice.

Yes:

Spam (1)

Dict ['key'] = list [index]

No:

Spam (1)

Dict ['key'] = list [index]

Don't add spaces at the end of the line.

Spaces are added before and after assignment (=), comparison (=,! =, =, in,not in,is,is not), Boolean symbol (and,or,not). Add spaces before and after the arithmetic operators (+, -, *, /,%, *, @) as appropriate

Yes:

X = = 1

No:

X

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report