mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
Project import generated by Copybara.
PiperOrigin-RevId: 222009069
This commit is contained in:
parent
ad22a7536d
commit
5b06d2d794
261
pyguide.md
261
pyguide.md
|
@ -59,7 +59,7 @@ Make sure you run `pylint` on your code.
|
|||
Suppress warnings if they are inappropriate so that other issues are not hidden.
|
||||
To suppress warnings, you can set a line-level comment:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
dict = 'something awful' # Bad Idea... pylint: disable=redefined-builtin
|
||||
```
|
||||
|
||||
|
@ -90,7 +90,7 @@ Unused argument warnings can be suppressed by deleting the variables at the
|
|||
beginning of the function. Always include a comment explaining why you are
|
||||
deleting it. "Unused." is sufficient. For example:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def viking_cafe_order(spam, beans, eggs=None):
|
||||
del beans, eggs # Unused by vikings.
|
||||
return spam + spam + spam
|
||||
|
@ -140,7 +140,7 @@ name with no prefix.
|
|||
|
||||
For example the module `sound.effects.echo` may be imported as follows:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from sound.effects import echo
|
||||
...
|
||||
echo.EchoFilter(input, output, delay=0.7, atten=4)
|
||||
|
@ -176,7 +176,7 @@ All new code should import each module by its full package name.
|
|||
|
||||
Imports should be as follows:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
# Reference in code with complete name.
|
||||
import absl.flags
|
||||
|
||||
|
@ -228,7 +228,7 @@ Exceptions must follow certain conditions:
|
|||
statement. For example:
|
||||
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
def connect_to_next_port(self, minimum):
|
||||
"""Connects to the next available port.
|
||||
|
@ -250,7 +250,7 @@ Exceptions must follow certain conditions:
|
|||
return port
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
def connect_to_next_port(self, minimum):
|
||||
"""Connects to the next available port.
|
||||
|
@ -289,7 +289,7 @@ Exceptions must follow certain conditions:
|
|||
- When capturing an exception, use `as` rather than a comma. For example:
|
||||
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
try:
|
||||
raise Error()
|
||||
except Error as error:
|
||||
|
@ -402,7 +402,7 @@ expression, `for` clause, filter expression. Multiple `for` clauses or filter
|
|||
expressions are not permitted. Use loops instead when things get more
|
||||
complicated.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
result = [mapping_expr for value in iterable if filter_expr]
|
||||
|
||||
|
@ -436,7 +436,7 @@ Yes:
|
|||
if jelly_bean.color == 'black')
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
result = [complicated_transform(
|
||||
x, some_argument=x+1)
|
||||
|
@ -486,7 +486,7 @@ dictionaries, and files. The built-in types define iterator methods, too. Prefer
|
|||
these methods to methods that return lists, except that you should not mutate a
|
||||
container while iterating over it.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: for key in adict: ...
|
||||
if key not in adict: ...
|
||||
if obj in alist: ...
|
||||
|
@ -494,7 +494,7 @@ Yes: for key in adict: ...
|
|||
for k, v in dict.iteritems(): ...
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: for key in adict.keys(): ...
|
||||
if not adict.has_key(key): ...
|
||||
for line in afile.readlines(): ...
|
||||
|
@ -636,7 +636,7 @@ Okay to use with the following caveat:
|
|||
Do not use mutable objects as default values in the function or method
|
||||
definition.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: def foo(a, b=None):
|
||||
if b is None:
|
||||
b = []
|
||||
|
@ -647,7 +647,7 @@ Yes: def foo(a, b: Sequence = ()): # Empty tuple OK since tuples are immutable
|
|||
...
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: def foo(a, b=[]):
|
||||
...
|
||||
No: def foo(a, b=time.time()): # The time the module was loaded???
|
||||
|
@ -697,7 +697,7 @@ overridden. Thus one must make sure that accessor methods are called indirectly
|
|||
to ensure methods overridden in subclasses are called by the property (using the
|
||||
Template Method DP).
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: import math
|
||||
|
||||
class Square(object):
|
||||
|
@ -792,7 +792,7 @@ Use the "implicit" false if at all possible, e.g., `if foo:` rather than
|
|||
known to be an integer (and is not the result of `len()`) against the
|
||||
integer 0.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: if not users:
|
||||
print('no users')
|
||||
|
||||
|
@ -807,7 +807,7 @@ Use the "implicit" false if at all possible, e.g., `if foo:` rather than
|
|||
x = []
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: if len(users) == 0:
|
||||
print('no users')
|
||||
|
||||
|
@ -844,7 +844,7 @@ generally preferable.
|
|||
We do not use any Python version which does not support these features, so there
|
||||
is no reason not to use the new styles.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: words = foo.split(':')
|
||||
|
||||
[x[1] for x in my_list if x[2] == 5]
|
||||
|
@ -854,7 +854,7 @@ Yes: words = foo.split(':')
|
|||
fn(*args, **kwargs)
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: words = string.split(foo, ':')
|
||||
|
||||
map(lambda x: x[1], filter(lambda x: x[2] == 5, my_list))
|
||||
|
@ -880,7 +880,7 @@ occurs, the name is treated as a global variable.
|
|||
|
||||
An example of the use of this feature is:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def get_adder(summand1):
|
||||
"""Returns a function that adds numbers to a given number."""
|
||||
def adder(summand2):
|
||||
|
@ -901,7 +901,7 @@ experienced Lisp and Scheme (and Haskell and ML and ...) programmers.
|
|||
Can lead to confusing bugs. Such as this example based on
|
||||
[PEP-0227](http://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0227/):
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
i = 4
|
||||
def foo(x):
|
||||
def bar():
|
||||
|
@ -939,7 +939,7 @@ converting ordinary methods into dynamically computed attributes. However, the
|
|||
decorator syntax allows for user-defined decorators as well. Specifically, for
|
||||
some function `my_decorator`, this:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
class C(object):
|
||||
@my_decorator
|
||||
def method(self):
|
||||
|
@ -949,7 +949,7 @@ class C(object):
|
|||
is equivalent to:
|
||||
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
class C(object):
|
||||
def method(self):
|
||||
# method body ...
|
||||
|
@ -1085,7 +1085,7 @@ Use of `from __future__ import` statements is encouraged. All new code should
|
|||
contain the following and existing code should be updated to be compatible when
|
||||
possible:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
@ -1135,13 +1135,13 @@ modules.
|
|||
Type annotations (or "type hints") are for function or method arguments and
|
||||
return values:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def func(a: int) -> List[int]:
|
||||
```
|
||||
|
||||
You can also declare the type of a variable using a special comment:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
a = SomeFunc() # type: SomeType
|
||||
```
|
||||
|
||||
|
@ -1196,7 +1196,7 @@ Make use of Python's [implicit line joining inside parentheses, brackets and
|
|||
braces](http://docs.python.org/reference/lexical_analysis.html#implicit-line-joining).
|
||||
If necessary, you can add an extra pair of parentheses around an expression.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: foo_bar(self, width, height, color='black', design=None, x='foo',
|
||||
emphasis=None, highlight=0)
|
||||
|
||||
|
@ -1207,19 +1207,19 @@ Yes: foo_bar(self, width, height, color='black', design=None, x='foo',
|
|||
When a literal string won't fit on a single line, use parentheses for implicit
|
||||
line joining.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
x = ('This will build a very long long '
|
||||
'long long long long long long string')
|
||||
```
|
||||
|
||||
Within comments, put long URLs on their own line if necessary.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: # See details at
|
||||
# http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: # See details at
|
||||
# http://www.example.com/us/developer/documentation/api/content/\
|
||||
# v2.0/csv_file_name_extension_full_specification.html
|
||||
|
@ -1229,20 +1229,20 @@ It is permissible to use backslash continuation when defining a `with` statement
|
|||
whose expressions span three or more lines. For two lines of expressions, use a
|
||||
nested `with` statement:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
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)
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: with VeryLongFirstExpressionFunction() as spam, \
|
||||
VeryLongSecondExpressionFunction() as beans:
|
||||
PlaceOrder(eggs, beans, spam, beans)
|
||||
```
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: with very_long_first_expression_function() as spam:
|
||||
with very_long_second_expression_function() as beans:
|
||||
place_order(beans, spam)
|
||||
|
@ -1261,7 +1261,7 @@ It is fine, though not required, to use parentheses around tuples. Do not use
|
|||
them in return statements or conditional statements unless using parentheses for
|
||||
implied line continuation or to indicate a tuple.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: if foo:
|
||||
bar()
|
||||
while x:
|
||||
|
@ -1278,7 +1278,7 @@ Yes: if foo:
|
|||
for (x, y) in dict.items(): ...
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: if (x):
|
||||
bar()
|
||||
if not(x):
|
||||
|
@ -1299,7 +1299,7 @@ you should align wrapped elements either vertically, as per the examples in the
|
|||
in which case there should be nothing after the open parenthesis or bracket on
|
||||
the first line.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: # Aligned with opening delimiter
|
||||
foo = long_function_name(var_one, var_two,
|
||||
var_three, var_four)
|
||||
|
@ -1329,7 +1329,7 @@ Yes: # Aligned with opening delimiter
|
|||
}
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: # Stuff on first line forbidden
|
||||
foo = long_function_name(var_one, var_two,
|
||||
var_three, var_four)
|
||||
|
@ -1360,7 +1360,7 @@ element. The presence of a trailing comma is also used as a hint to our Python
|
|||
code auto-formatter [YAPF](https://pypi.org/project/yapf/) to direct it to auto-format the container
|
||||
of items to one item per line when the `,` after the final element is present.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: golomb3 = [0, 1, 3]
|
||||
Yes: golomb4 = [
|
||||
0,
|
||||
|
@ -1370,7 +1370,7 @@ Yes: golomb4 = [
|
|||
]
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: golomb4 = [
|
||||
0,
|
||||
1,
|
||||
|
@ -1396,24 +1396,24 @@ Follow standard typographic rules for the use of spaces around punctuation.
|
|||
|
||||
No whitespace inside parentheses, brackets or braces.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: spam(ham[1], {eggs: 2}, [])
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: spam( ham[ 1 ], { eggs: 2 }, [ ] )
|
||||
```
|
||||
|
||||
No whitespace before a comma, semicolon, or colon. Do use whitespace after a
|
||||
comma, semicolon, or colon except at the end of the line.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: if x == 4:
|
||||
print(x, y)
|
||||
x, y = y, x
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: if x == 4 :
|
||||
print(x , y)
|
||||
x , y = y , x
|
||||
|
@ -1422,20 +1422,20 @@ No: if x == 4 :
|
|||
No whitespace before the open paren/bracket that starts an argument list,
|
||||
indexing or slicing.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: spam(1)
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: spam (1)
|
||||
```
|
||||
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: dict['key'] = list[index]
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: dict ['key'] = list [index]
|
||||
```
|
||||
|
||||
|
@ -1444,11 +1444,11 @@ Surround binary operators with a single space on either side for assignment
|
|||
Booleans (`and, or, not`). Use your better judgment for the insertion of spaces
|
||||
around arithmetic operators (`+`, `-`, `*`, `/`, `//`, `%`, `**`, `@`).
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: x == 1
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: x<1
|
||||
```
|
||||
|
||||
|
@ -1457,12 +1457,12 @@ Only use spaces around the '=' sign defining a default parameter value
|
|||
[when a type annotation is present](#typing-default-values),
|
||||
do not use spaces around '=' for default parameter values otherwise.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: def complex(real, imag=0.0): return Magic(r=real, i=imag)
|
||||
Yes: def complex(real, imag: float = 0.0): return Magic(r=real, i=imag)
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: def complex(real, imag = 0.0): return Magic(r = real, i = imag)
|
||||
No: def complex(real, imag: float=0.0): return Magic(r = real, i = imag)
|
||||
```
|
||||
|
@ -1470,7 +1470,7 @@ No: def complex(real, imag: float=0.0): return Magic(r = real, i = imag)
|
|||
Don't use spaces to vertically align tokens on consecutive lines, since it
|
||||
becomes a maintenance burden (applies to `:`, `#`, `=`, etc.):
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
foo = 1000 # comment
|
||||
long_name = 2 # comment that should not be aligned
|
||||
|
@ -1481,7 +1481,7 @@ Yes:
|
|||
}
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
foo = 1000 # comment
|
||||
long_name = 2 # comment that should not be aligned
|
||||
|
@ -1592,7 +1592,7 @@ Sections should be indented two spaces, except for the heading.
|
|||
[*Raises:*](#doc-function-raises) {#doc-function-raises}
|
||||
: List all exceptions that are relevant to the interface.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
|
||||
"""Fetches rows from a Bigtable.
|
||||
|
||||
|
@ -1633,7 +1633,7 @@ If your class has public attributes, they should be documented here in an
|
|||
`Attributes` section and follow the same formatting as a
|
||||
[function's `Args`](#doc-function-args) section.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
class SampleClass(object):
|
||||
"""Summary of class here.
|
||||
|
||||
|
@ -1664,7 +1664,7 @@ review](http://en.wikipedia.org/wiki/Code_review), you should comment it
|
|||
now. Complicated operations get a few lines of comments before the operations
|
||||
commence. Non-obvious ones get comments at the end of the line.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
# 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
|
||||
|
@ -1679,7 +1679,7 @@ code.
|
|||
On the other hand, never describe the code. Assume the person reading the code
|
||||
knows Python (though not what you're trying to do) better than you do.
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
# BAD COMMENT: Now go through the b array and make sure whenever i occurs
|
||||
# the next element is i+1
|
||||
```
|
||||
|
@ -1709,7 +1709,7 @@ punctuation, spelling, and grammar help with that goal.
|
|||
If a class inherits from no other base classes, explicitly inherit from
|
||||
`object`. This also applies to nested classes.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: class SampleClass(object):
|
||||
pass
|
||||
|
||||
|
@ -1725,7 +1725,7 @@ Yes: class SampleClass(object):
|
|||
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: class SampleClass:
|
||||
pass
|
||||
|
||||
|
@ -1750,7 +1750,7 @@ Use the `format` method or the `%` operator for formatting strings, even when
|
|||
the parameters are all strings. Use your best judgement to decide between `+`
|
||||
and `%` (or `format`) though.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: x = a + b
|
||||
x = '%s, %s!' % (imperative, expletive)
|
||||
x = '{}, {}'.format(first, second)
|
||||
|
@ -1759,7 +1759,7 @@ Yes: x = a + b
|
|||
x = f'name: {name}; score: {n}' # Python 3.6+
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: x = '%s%s' % (a, b) # use + in this case
|
||||
x = '{}{}'.format(a, b) # use + in this case
|
||||
x = first + ', ' + second
|
||||
|
@ -1772,7 +1772,7 @@ results in quadratic rather than linear running time. Instead, add each
|
|||
substring to a list and `''.join` the list after the loop terminates (or, write
|
||||
each substring to a `io.BytesIO` buffer).
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: items = ['<table>']
|
||||
for last_name, first_name in employee_list:
|
||||
items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name))
|
||||
|
@ -1780,7 +1780,7 @@ Yes: items = ['<table>']
|
|||
employee_table = ''.join(items)
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: employee_table = '<table>'
|
||||
for last_name, first_name in employee_list:
|
||||
employee_table += '<tr><td>%s, %s</td></tr>' % (last_name, first_name)
|
||||
|
@ -1792,14 +1792,14 @@ or `"` and stick with it. It is okay to use the other quote character on a
|
|||
string to avoid the need to `\\` escape within the string. `gpylint` enforces
|
||||
this.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
Python('Why are you hiding your eyes?')
|
||||
Gollum("I'm scared of lint errors.")
|
||||
Narrator('"Good!" thought a happy Python reviewer.')
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
Python("Why are you hiding your eyes?")
|
||||
Gollum('The lint. It burns. It burns us.')
|
||||
|
@ -1812,13 +1812,13 @@ use `'''` for all non-docstring multi-line strings if and only if they also use
|
|||
often cleaner to use implicit line joining since multi-line strings do not flow
|
||||
with the indentation of the rest of the program:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
print("This is much nicer.\n"
|
||||
"Do it this way.\n")
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
print("""This is pretty ugly.
|
||||
Don't do this.
|
||||
|
@ -1858,7 +1858,7 @@ file is poor practice, for several reasons:
|
|||
The preferred way to manage files is using the ["with"
|
||||
statement](http://docs.python.org/reference/compound_stmts.html#the-with-statement):
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
with open("hello.txt") as hello_file:
|
||||
for line in hello_file:
|
||||
print(line)
|
||||
|
@ -1867,7 +1867,7 @@ with open("hello.txt") as hello_file:
|
|||
For file-like objects that do not support the "with" statement, use
|
||||
`contextlib.closing()`:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
import contextlib
|
||||
|
||||
with contextlib.closing(urllib.urlopen("http://www.python.org/")) as front_page:
|
||||
|
@ -1890,7 +1890,7 @@ The main purpose is to have a consistent `TODO` format that can be searched to
|
|||
find out how to get more details upon request. A `TODO` is not a commitment that
|
||||
the person referenced will fix the problem. Thus when you create a `TODO`, it is almost always your name that is given.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
# TODO(kl@gmail.com): Use a "*" here for string repetition.
|
||||
# TODO(Zeke) Change this to use relations.
|
||||
```
|
||||
|
@ -1907,12 +1907,12 @@ Imports should be on separate lines.
|
|||
|
||||
E.g.:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes: import os
|
||||
import sys
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No: import os, sys
|
||||
```
|
||||
|
||||
|
@ -1923,7 +1923,7 @@ grouped with the order being most generic to least generic:
|
|||
|
||||
1. Python standard library imports. For example:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
import sys
|
||||
```
|
||||
|
||||
|
@ -1931,7 +1931,7 @@ grouped with the order being most generic to least generic:
|
|||
module or package imports. For example:
|
||||
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
import tensorflow as tf
|
||||
```
|
||||
|
||||
|
@ -1939,7 +1939,7 @@ grouped with the order being most generic to least generic:
|
|||
sub-package imports. For example:
|
||||
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from otherproject.ai import mind
|
||||
```
|
||||
|
||||
|
@ -1948,7 +1948,7 @@ grouped with the order being most generic to least generic:
|
|||
sub-package as this file. For example:
|
||||
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from myproject.backend.hgwells import time_machine
|
||||
```
|
||||
|
||||
|
@ -1962,7 +1962,7 @@ Within each grouping, imports should be sorted lexicographically, ignoring case,
|
|||
according to each module's full package path. Code may optionally place a blank
|
||||
line between import sections.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
import collections
|
||||
import queue
|
||||
import sys
|
||||
|
@ -1997,13 +1997,13 @@ the entire statement fits on one line. In particular, you can never do so with
|
|||
`try`/`except` since the `try` and `except` can't both fit on the same line, and
|
||||
you can only do so with an `if` if there is no `else`.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
|
||||
if foo: bar(foo)
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
|
||||
if foo: bar(foo)
|
||||
|
@ -2204,7 +2204,7 @@ In Python, `pydoc` as well as unit tests require modules to be importable. Your
|
|||
code should always check `if __name__ == '__main__'` before executing your main
|
||||
program so that the main program is not executed when the module is imported.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def main():
|
||||
...
|
||||
|
||||
|
@ -2269,7 +2269,7 @@ Try to follow the existing [indentation](#indentation) rules.
|
|||
|
||||
After annotating, many function signatures will become "one parameter per line".
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def my_method(self,
|
||||
first_var: int,
|
||||
second_var: Foo,
|
||||
|
@ -2281,7 +2281,7 @@ Always prefer breaking between variables, and not for example between variable
|
|||
names and type annotations. However, if everything fits on the same line,
|
||||
go for it.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def my_method(self, first_var: int) -> int:
|
||||
...
|
||||
```
|
||||
|
@ -2289,7 +2289,7 @@ def my_method(self, first_var: int) -> int:
|
|||
If the combination of the function name, the last parameter, and the return type
|
||||
is too long, indent by 4 in a new line.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def my_method(
|
||||
self, first_var: int) -> Tuple[MyLongType1, MyLongType1]:
|
||||
...
|
||||
|
@ -2299,7 +2299,7 @@ When the return type does not fit on the same line as the last parameter, the
|
|||
preferred way is to indent the parameters by 4 on a new line and align the
|
||||
closing parenthesis with the def.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
def my_method(
|
||||
self, **kw_args: Optional[MyLongType]
|
||||
|
@ -2310,7 +2310,7 @@ def my_method(
|
|||
`pylint` allows you to move the closing parenthesis to a new line and align
|
||||
with the opening one, but this is less readable.
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
def my_method(self,
|
||||
**kw_args: Optional[MyLongType]
|
||||
|
@ -2321,7 +2321,7 @@ def my_method(self,
|
|||
As in the examples above, prefer not to break types. However, sometimes they are
|
||||
too long to be on a single line (try to keep sub-types unbroken).
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def my_method(
|
||||
self,
|
||||
first_var: Tuple[List[MyLongType1],
|
||||
|
@ -2335,7 +2335,7 @@ If a single name and type is too long, consider using an
|
|||
[alias](#typing-aliases) for the type. The last resort is to break after the
|
||||
colon and indent by 4.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
def my_function(
|
||||
long_variable_name:
|
||||
|
@ -2344,7 +2344,7 @@ def my_function(
|
|||
...
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
def my_function(
|
||||
long_variable_name: long_module_name.
|
||||
|
@ -2361,7 +2361,7 @@ If you need to use a class name from the same module that is not yet defined --
|
|||
for example, if you need the class inside the class declaration, or if you use a
|
||||
class that is defined below -- use a string for the class name.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
class MyClass(object):
|
||||
|
||||
def __init__(self,
|
||||
|
@ -2377,12 +2377,12 @@ when combining an argument annotation with a default value, use spaces around
|
|||
the = sign (but only for those arguments that have both an annotation and a
|
||||
default).
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
def func(a: int = 0) -> int:
|
||||
...
|
||||
```
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
def func(a:int=0) -> int:
|
||||
...
|
||||
|
@ -2401,7 +2401,7 @@ Use explicit `Optional` instead of implicit `Optional`. Earlier versions of PEP
|
|||
484 allowed `a: Text = None` to be interpretted as `a: Optional[Text] = None`,
|
||||
but that is no longer the preferred behavior.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
Yes:
|
||||
def func(a: Optional[Text], b: Optional[Text] = None) -> Text:
|
||||
...
|
||||
|
@ -2409,7 +2409,7 @@ def multiple_nullable_union(a: Union[None, Text, int]) -> Text
|
|||
...
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
No:
|
||||
def nullable_union(a: Union[None, Text]) -> Text:
|
||||
...
|
||||
|
@ -2428,7 +2428,7 @@ returned tuples). If the alias is used only in this module, it should be
|
|||
|
||||
For example, if the name of module together with the type is too long:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
SomeType = module_with_long_name.TypeWithLongName
|
||||
```
|
||||
|
||||
|
@ -2444,7 +2444,7 @@ You can disable type checking on a line with the special comment
|
|||
|
||||
`pytype` has a disable option for specific errors (similar to lint):
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
# pytype: disable=attribute-error
|
||||
```
|
||||
|
||||
|
@ -2455,7 +2455,7 @@ You can disable type checking on a line with the special comment
|
|||
If an internal variable has a type that is hard or impossible to infer, you can
|
||||
supply it as a special comment:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
a = SomeUndecoratedFunction() # type: Foo
|
||||
```
|
||||
<a id="s3.19.9-tuples"></a>
|
||||
|
@ -2466,7 +2466,7 @@ Unlike Lists, which can only have a single type, Tuples can have either a single
|
|||
repeated type or a set number of elements with different types. The latter is
|
||||
commonly used as return type from a function.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
a = [1, 2, 3] # type: List[int]
|
||||
b = (1, 2, 3) # type: Tuple[int, ...]
|
||||
c = (1, "2", 3.5) # type: Tuple[int, Text, float]
|
||||
|
@ -2482,7 +2482,7 @@ function `TypeVar` is a common way to use them.
|
|||
|
||||
Example:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from typing import List, TypeVar
|
||||
T = TypeVar("T")
|
||||
...
|
||||
|
@ -2492,7 +2492,7 @@ def next(l: List[T]) -> T:
|
|||
|
||||
A TypeVar can be constrained:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
AddableType = TypeVar("AddableType", int, float, Text)
|
||||
def add(a: AddableType, b: AddableType) -> AddableType:
|
||||
return a + b
|
||||
|
@ -2502,7 +2502,7 @@ A common predefined type variable in the `typing` module is `AnyStr`. Use it for
|
|||
multiple annotations that can be `bytes` or `unicode` and must all be the same
|
||||
type.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from typing import AnyStr
|
||||
def check_length(x: AnyStr) -> AnyStr:
|
||||
if len(x) <= 42:
|
||||
|
@ -2514,40 +2514,55 @@ def check_length(x: AnyStr) -> AnyStr:
|
|||
<a id="typing-strings"></a>
|
||||
#### 3.19.11 Strings types
|
||||
|
||||
When annotating functions that take or return strings, avoid using `str`,
|
||||
because it means different things in Python 2 and Python 3. In Python 2, `str`
|
||||
is `bytes`; in Python 3, it is `unicode`. Whenever possible, it is best to be
|
||||
explicit:
|
||||
The proper type for annotating strings depends on what versions of Python the
|
||||
code is intended for.
|
||||
|
||||
```python {.bad}
|
||||
For Python 3 only code, prefer to use `str`. `Text` is also acceptable. Be
|
||||
consistent in using one or the other.
|
||||
|
||||
For Python 2 compatible code, use `Text`. In some rare cases, `str` may make
|
||||
sense; typically to aid compatiblity when the return types aren't the same
|
||||
between the two Python versions. Avoid using `unicode`: it doesn't exist in
|
||||
Python 3.
|
||||
|
||||
The reason this discreprency exists is because `str` means different things
|
||||
depending on the Python version.
|
||||
|
||||
```python
|
||||
No:
|
||||
def f(x: str) -> str:
|
||||
def py2_code(x: str) -> unicode:
|
||||
...
|
||||
```
|
||||
|
||||
For code that deals with byte arrays, use `bytes`.
|
||||
For code that deals with binary data, use `bytes`.
|
||||
|
||||
```python {.good}
|
||||
def f(x: bytes) -> bytes:
|
||||
```python
|
||||
def deals_with_binary_data(x: bytes) -> bytes:
|
||||
...
|
||||
```
|
||||
|
||||
For code that processes text data (`str` or `unicode` in Python 2, `str` in
|
||||
Python 3), use `Text`.
|
||||
For Python 2 compatible code that processes text data (`str` or `unicode` in
|
||||
Python 2, `str` in Python 3), use `Text`. For Python 3 only code that process
|
||||
text data, prefer `str`.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from typing import Text
|
||||
...
|
||||
def f(x: Text) -> Text:
|
||||
def py2_compatible(x: Text) -> Text:
|
||||
...
|
||||
def py3_only(x: str) -> str:
|
||||
...
|
||||
```
|
||||
|
||||
If the type can be either byte arrays or text, use `Union`.
|
||||
If the type can be either bytes or text, use `Union`, with the appropriate text
|
||||
type.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from typing import Text, Union
|
||||
...
|
||||
def f(x: Union[bytes, Text]) -> Union[bytes, Text]:
|
||||
def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]:
|
||||
...
|
||||
def py3_only(x: Union[bytes, str]) -> Union[bytes, str]:
|
||||
...
|
||||
```
|
||||
|
||||
|
@ -2565,7 +2580,7 @@ For classes from the `typing` module, always import the class itself. You are
|
|||
explicitly allowed to import multiple specific classes on one line from the
|
||||
`typing` module. Ex:
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from typing import Any, Dict, Optional
|
||||
```
|
||||
|
||||
|
@ -2575,7 +2590,7 @@ not be defined in your Python code, typed or not. If there is a collision
|
|||
between a type and an existing name in a module, import it using
|
||||
`import x as y`.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from typing import Any as AnyType
|
||||
```
|
||||
|
||||
|
@ -2601,7 +2616,7 @@ Imports that are needed only for type annotations can be placed within an
|
|||
- There should be no empty lines in the typing imports list.
|
||||
- Sort this list as if it were a regular imports list.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
import typing
|
||||
if typing.TYPE_CHECKING:
|
||||
import sketch
|
||||
|
@ -2622,7 +2637,7 @@ Replace modules that create circular dependency imports with `Any`. Set an
|
|||
this module (any attribute of Any is Any). Alias definitions should be separated
|
||||
from the last import by one line.
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
from typing import Any
|
||||
|
||||
some_mod = Any # some_mod.py imports this module.
|
||||
|
@ -2640,12 +2655,12 @@ def my_method(self, var: some_mod.SomeType) -> None:
|
|||
When annotating, prefer to specify type parameters for generic types; otherwise,
|
||||
[the generics' parameters will be assumed to be `Any`](https://www.python.org/dev/peps/pep-0484/#the-any-type).
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
def get_names(employee_ids: List[int]) -> Dict[int, Any]:
|
||||
...
|
||||
```
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
# These are both interpreted as get_names(employee_ids: List[Any]) -> Dict[Any, Any]
|
||||
def get_names(employee_ids: list) -> Dict:
|
||||
...
|
||||
|
@ -2658,12 +2673,12 @@ If the best type parameter for a generic is `Any`, make it explicit, but
|
|||
remember that in many cases [`TypeVar`](#typing-type-var) might be more
|
||||
appropriate:
|
||||
|
||||
```python {.bad}
|
||||
```python
|
||||
def get_names(employee_ids: List[Any]) -> Dict[Any, Text]:
|
||||
"""Returns a mapping from employee ID to employee name for given IDs."""
|
||||
```
|
||||
|
||||
```python {.good}
|
||||
```python
|
||||
T = TypeVar('T')
|
||||
def get_names(employee_ids: List[T]) -> Dict[T, Text]:
|
||||
"""Returns a mapping from employee ID to employee name for given IDs."""
|
||||
|
|
Loading…
Reference in New Issue
Block a user