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.
|
Suppress warnings if they are inappropriate so that other issues are not hidden.
|
||||||
To suppress warnings, you can set a line-level comment:
|
To suppress warnings, you can set a line-level comment:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
dict = 'something awful' # Bad Idea... pylint: disable=redefined-builtin
|
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
|
beginning of the function. Always include a comment explaining why you are
|
||||||
deleting it. "Unused." is sufficient. For example:
|
deleting it. "Unused." is sufficient. For example:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
def viking_cafe_order(spam, beans, eggs=None):
|
def viking_cafe_order(spam, beans, eggs=None):
|
||||||
del beans, eggs # Unused by vikings.
|
del beans, eggs # Unused by vikings.
|
||||||
return spam + spam + spam
|
return spam + spam + spam
|
||||||
|
@ -140,7 +140,7 @@ name with no prefix.
|
||||||
|
|
||||||
For example the module `sound.effects.echo` may be imported as follows:
|
For example the module `sound.effects.echo` may be imported as follows:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
from sound.effects import echo
|
from sound.effects import echo
|
||||||
...
|
...
|
||||||
echo.EchoFilter(input, output, delay=0.7, atten=4)
|
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:
|
Imports should be as follows:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
# Reference in code with complete name.
|
# Reference in code with complete name.
|
||||||
import absl.flags
|
import absl.flags
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ Exceptions must follow certain conditions:
|
||||||
statement. For example:
|
statement. For example:
|
||||||
|
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
def connect_to_next_port(self, minimum):
|
def connect_to_next_port(self, minimum):
|
||||||
"""Connects to the next available port.
|
"""Connects to the next available port.
|
||||||
|
@ -250,7 +250,7 @@ Exceptions must follow certain conditions:
|
||||||
return port
|
return port
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No:
|
No:
|
||||||
def connect_to_next_port(self, minimum):
|
def connect_to_next_port(self, minimum):
|
||||||
"""Connects to the next available port.
|
"""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:
|
- When capturing an exception, use `as` rather than a comma. For example:
|
||||||
|
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
try:
|
try:
|
||||||
raise Error()
|
raise Error()
|
||||||
except Error as 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
|
expressions are not permitted. Use loops instead when things get more
|
||||||
complicated.
|
complicated.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
result = [mapping_expr for value in iterable if filter_expr]
|
result = [mapping_expr for value in iterable if filter_expr]
|
||||||
|
|
||||||
|
@ -436,7 +436,7 @@ Yes:
|
||||||
if jelly_bean.color == 'black')
|
if jelly_bean.color == 'black')
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No:
|
No:
|
||||||
result = [complicated_transform(
|
result = [complicated_transform(
|
||||||
x, some_argument=x+1)
|
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
|
these methods to methods that return lists, except that you should not mutate a
|
||||||
container while iterating over it.
|
container while iterating over it.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: for key in adict: ...
|
Yes: for key in adict: ...
|
||||||
if key not in adict: ...
|
if key not in adict: ...
|
||||||
if obj in alist: ...
|
if obj in alist: ...
|
||||||
|
@ -494,7 +494,7 @@ Yes: for key in adict: ...
|
||||||
for k, v in dict.iteritems(): ...
|
for k, v in dict.iteritems(): ...
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: for key in adict.keys(): ...
|
No: for key in adict.keys(): ...
|
||||||
if not adict.has_key(key): ...
|
if not adict.has_key(key): ...
|
||||||
for line in afile.readlines(): ...
|
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
|
Do not use mutable objects as default values in the function or method
|
||||||
definition.
|
definition.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: def foo(a, b=None):
|
Yes: def foo(a, b=None):
|
||||||
if b is None:
|
if b is None:
|
||||||
b = []
|
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=[]):
|
||||||
...
|
...
|
||||||
No: def foo(a, b=time.time()): # The time the module was loaded???
|
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
|
to ensure methods overridden in subclasses are called by the property (using the
|
||||||
Template Method DP).
|
Template Method DP).
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: import math
|
Yes: import math
|
||||||
|
|
||||||
class Square(object):
|
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
|
known to be an integer (and is not the result of `len()`) against the
|
||||||
integer 0.
|
integer 0.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: if not users:
|
Yes: if not users:
|
||||||
print('no users')
|
print('no users')
|
||||||
|
|
||||||
|
@ -807,7 +807,7 @@ Use the "implicit" false if at all possible, e.g., `if foo:` rather than
|
||||||
x = []
|
x = []
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: if len(users) == 0:
|
No: if len(users) == 0:
|
||||||
print('no users')
|
print('no users')
|
||||||
|
|
||||||
|
@ -844,7 +844,7 @@ generally preferable.
|
||||||
We do not use any Python version which does not support these features, so there
|
We do not use any Python version which does not support these features, so there
|
||||||
is no reason not to use the new styles.
|
is no reason not to use the new styles.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: words = foo.split(':')
|
Yes: words = foo.split(':')
|
||||||
|
|
||||||
[x[1] for x in my_list if x[2] == 5]
|
[x[1] for x in my_list if x[2] == 5]
|
||||||
|
@ -854,7 +854,7 @@ Yes: words = foo.split(':')
|
||||||
fn(*args, **kwargs)
|
fn(*args, **kwargs)
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: words = string.split(foo, ':')
|
No: words = string.split(foo, ':')
|
||||||
|
|
||||||
map(lambda x: x[1], filter(lambda x: x[2] == 5, my_list))
|
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:
|
An example of the use of this feature is:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
def get_adder(summand1):
|
def get_adder(summand1):
|
||||||
"""Returns a function that adds numbers to a given number."""
|
"""Returns a function that adds numbers to a given number."""
|
||||||
def adder(summand2):
|
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
|
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/):
|
[PEP-0227](http://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0227/):
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
i = 4
|
i = 4
|
||||||
def foo(x):
|
def foo(x):
|
||||||
def bar():
|
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
|
decorator syntax allows for user-defined decorators as well. Specifically, for
|
||||||
some function `my_decorator`, this:
|
some function `my_decorator`, this:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
class C(object):
|
class C(object):
|
||||||
@my_decorator
|
@my_decorator
|
||||||
def method(self):
|
def method(self):
|
||||||
|
@ -949,7 +949,7 @@ class C(object):
|
||||||
is equivalent to:
|
is equivalent to:
|
||||||
|
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
class C(object):
|
class C(object):
|
||||||
def method(self):
|
def method(self):
|
||||||
# method body ...
|
# 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
|
contain the following and existing code should be updated to be compatible when
|
||||||
possible:
|
possible:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
@ -1135,13 +1135,13 @@ modules.
|
||||||
Type annotations (or "type hints") are for function or method arguments and
|
Type annotations (or "type hints") are for function or method arguments and
|
||||||
return values:
|
return values:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
def func(a: int) -> List[int]:
|
def func(a: int) -> List[int]:
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also declare the type of a variable using a special comment:
|
You can also declare the type of a variable using a special comment:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
a = SomeFunc() # type: SomeType
|
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).
|
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.
|
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',
|
Yes: foo_bar(self, width, height, color='black', design=None, x='foo',
|
||||||
emphasis=None, highlight=0)
|
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
|
When a literal string won't fit on a single line, use parentheses for implicit
|
||||||
line joining.
|
line joining.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
x = ('This will build a very long long '
|
x = ('This will build a very long long '
|
||||||
'long long long long long long string')
|
'long long long long long long string')
|
||||||
```
|
```
|
||||||
|
|
||||||
Within comments, put long URLs on their own line if necessary.
|
Within comments, put long URLs on their own line if necessary.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: # See details at
|
Yes: # See details at
|
||||||
# http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html
|
# 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
|
No: # See details at
|
||||||
# http://www.example.com/us/developer/documentation/api/content/\
|
# http://www.example.com/us/developer/documentation/api/content/\
|
||||||
# v2.0/csv_file_name_extension_full_specification.html
|
# 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
|
whose expressions span three or more lines. For two lines of expressions, use a
|
||||||
nested `with` statement:
|
nested `with` statement:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: with very_long_first_expression_function() as spam, \
|
Yes: with very_long_first_expression_function() as spam, \
|
||||||
very_long_second_expression_function() as beans, \
|
very_long_second_expression_function() as beans, \
|
||||||
third_thing() as eggs:
|
third_thing() as eggs:
|
||||||
place_order(eggs, beans, spam, beans)
|
place_order(eggs, beans, spam, beans)
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: with VeryLongFirstExpressionFunction() as spam, \
|
No: with VeryLongFirstExpressionFunction() as spam, \
|
||||||
VeryLongSecondExpressionFunction() as beans:
|
VeryLongSecondExpressionFunction() as beans:
|
||||||
PlaceOrder(eggs, beans, spam, beans)
|
PlaceOrder(eggs, beans, spam, beans)
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: with very_long_first_expression_function() as spam:
|
Yes: with very_long_first_expression_function() as spam:
|
||||||
with very_long_second_expression_function() as beans:
|
with very_long_second_expression_function() as beans:
|
||||||
place_order(beans, spam)
|
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
|
them in return statements or conditional statements unless using parentheses for
|
||||||
implied line continuation or to indicate a tuple.
|
implied line continuation or to indicate a tuple.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: if foo:
|
Yes: if foo:
|
||||||
bar()
|
bar()
|
||||||
while x:
|
while x:
|
||||||
|
@ -1278,7 +1278,7 @@ Yes: if foo:
|
||||||
for (x, y) in dict.items(): ...
|
for (x, y) in dict.items(): ...
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: if (x):
|
No: if (x):
|
||||||
bar()
|
bar()
|
||||||
if not(x):
|
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
|
in which case there should be nothing after the open parenthesis or bracket on
|
||||||
the first line.
|
the first line.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: # Aligned with opening delimiter
|
Yes: # Aligned with opening delimiter
|
||||||
foo = long_function_name(var_one, var_two,
|
foo = long_function_name(var_one, var_two,
|
||||||
var_three, var_four)
|
var_three, var_four)
|
||||||
|
@ -1329,7 +1329,7 @@ Yes: # Aligned with opening delimiter
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: # Stuff on first line forbidden
|
No: # Stuff on first line forbidden
|
||||||
foo = long_function_name(var_one, var_two,
|
foo = long_function_name(var_one, var_two,
|
||||||
var_three, var_four)
|
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
|
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.
|
of items to one item per line when the `,` after the final element is present.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: golomb3 = [0, 1, 3]
|
Yes: golomb3 = [0, 1, 3]
|
||||||
Yes: golomb4 = [
|
Yes: golomb4 = [
|
||||||
0,
|
0,
|
||||||
|
@ -1370,7 +1370,7 @@ Yes: golomb4 = [
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: golomb4 = [
|
No: golomb4 = [
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
|
@ -1396,24 +1396,24 @@ Follow standard typographic rules for the use of spaces around punctuation.
|
||||||
|
|
||||||
No whitespace inside parentheses, brackets or braces.
|
No whitespace inside parentheses, brackets or braces.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: spam(ham[1], {eggs: 2}, [])
|
Yes: spam(ham[1], {eggs: 2}, [])
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: spam( ham[ 1 ], { eggs: 2 }, [ ] )
|
No: spam( ham[ 1 ], { eggs: 2 }, [ ] )
|
||||||
```
|
```
|
||||||
|
|
||||||
No whitespace before a comma, semicolon, or colon. Do use whitespace after a
|
No whitespace before a comma, semicolon, or colon. Do use whitespace after a
|
||||||
comma, semicolon, or colon except at the end of the line.
|
comma, semicolon, or colon except at the end of the line.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: if x == 4:
|
Yes: if x == 4:
|
||||||
print(x, y)
|
print(x, y)
|
||||||
x, y = y, x
|
x, y = y, x
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: if x == 4 :
|
No: if x == 4 :
|
||||||
print(x , y)
|
print(x , y)
|
||||||
x , y = y , x
|
x , y = y , x
|
||||||
|
@ -1422,20 +1422,20 @@ No: if x == 4 :
|
||||||
No whitespace before the open paren/bracket that starts an argument list,
|
No whitespace before the open paren/bracket that starts an argument list,
|
||||||
indexing or slicing.
|
indexing or slicing.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: spam(1)
|
Yes: spam(1)
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: spam (1)
|
No: spam (1)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: dict['key'] = list[index]
|
Yes: dict['key'] = list[index]
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: dict ['key'] = list [index]
|
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
|
Booleans (`and, or, not`). Use your better judgment for the insertion of spaces
|
||||||
around arithmetic operators (`+`, `-`, `*`, `/`, `//`, `%`, `**`, `@`).
|
around arithmetic operators (`+`, `-`, `*`, `/`, `//`, `%`, `**`, `@`).
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: x == 1
|
Yes: x == 1
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: x<1
|
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),
|
[when a type annotation is present](#typing-default-values),
|
||||||
do not use spaces around '=' for default parameter values otherwise.
|
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=0.0): return Magic(r=real, i=imag)
|
||||||
Yes: def complex(real, imag: float = 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 = 0.0): return Magic(r = real, i = imag)
|
||||||
No: def complex(real, imag: float=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
|
Don't use spaces to vertically align tokens on consecutive lines, since it
|
||||||
becomes a maintenance burden (applies to `:`, `#`, `=`, etc.):
|
becomes a maintenance burden (applies to `:`, `#`, `=`, etc.):
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
foo = 1000 # comment
|
foo = 1000 # comment
|
||||||
long_name = 2 # comment that should not be aligned
|
long_name = 2 # comment that should not be aligned
|
||||||
|
@ -1481,7 +1481,7 @@ Yes:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No:
|
No:
|
||||||
foo = 1000 # comment
|
foo = 1000 # comment
|
||||||
long_name = 2 # comment that should not be aligned
|
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}
|
[*Raises:*](#doc-function-raises) {#doc-function-raises}
|
||||||
: List all exceptions that are relevant to the interface.
|
: List all exceptions that are relevant to the interface.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
|
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
|
||||||
"""Fetches rows from a Bigtable.
|
"""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
|
`Attributes` section and follow the same formatting as a
|
||||||
[function's `Args`](#doc-function-args) section.
|
[function's `Args`](#doc-function-args) section.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
class SampleClass(object):
|
class SampleClass(object):
|
||||||
"""Summary of class here.
|
"""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
|
now. Complicated operations get a few lines of comments before the operations
|
||||||
commence. Non-obvious ones get comments at the end of the line.
|
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
|
# We use a weighted dictionary search to find out where i is in
|
||||||
# the array. We extrapolate position based on the largest num
|
# the array. We extrapolate position based on the largest num
|
||||||
# in the array and the array size and then do binary search to
|
# 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
|
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.
|
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
|
# BAD COMMENT: Now go through the b array and make sure whenever i occurs
|
||||||
# the next element is i+1
|
# 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
|
If a class inherits from no other base classes, explicitly inherit from
|
||||||
`object`. This also applies to nested classes.
|
`object`. This also applies to nested classes.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: class SampleClass(object):
|
Yes: class SampleClass(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1725,7 +1725,7 @@ Yes: class SampleClass(object):
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: class SampleClass:
|
No: class SampleClass:
|
||||||
pass
|
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 `+`
|
the parameters are all strings. Use your best judgement to decide between `+`
|
||||||
and `%` (or `format`) though.
|
and `%` (or `format`) though.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: x = a + b
|
Yes: x = a + b
|
||||||
x = '%s, %s!' % (imperative, expletive)
|
x = '%s, %s!' % (imperative, expletive)
|
||||||
x = '{}, {}'.format(first, second)
|
x = '{}, {}'.format(first, second)
|
||||||
|
@ -1759,7 +1759,7 @@ Yes: x = a + b
|
||||||
x = f'name: {name}; score: {n}' # Python 3.6+
|
x = f'name: {name}; score: {n}' # Python 3.6+
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: x = '%s%s' % (a, b) # use + in this case
|
No: x = '%s%s' % (a, b) # use + in this case
|
||||||
x = '{}{}'.format(a, b) # use + in this case
|
x = '{}{}'.format(a, b) # use + in this case
|
||||||
x = first + ', ' + second
|
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
|
substring to a list and `''.join` the list after the loop terminates (or, write
|
||||||
each substring to a `io.BytesIO` buffer).
|
each substring to a `io.BytesIO` buffer).
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: items = ['<table>']
|
Yes: items = ['<table>']
|
||||||
for last_name, first_name in employee_list:
|
for last_name, first_name in employee_list:
|
||||||
items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name))
|
items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name))
|
||||||
|
@ -1780,7 +1780,7 @@ Yes: items = ['<table>']
|
||||||
employee_table = ''.join(items)
|
employee_table = ''.join(items)
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: employee_table = '<table>'
|
No: employee_table = '<table>'
|
||||||
for last_name, first_name in employee_list:
|
for last_name, first_name in employee_list:
|
||||||
employee_table += '<tr><td>%s, %s</td></tr>' % (last_name, first_name)
|
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
|
string to avoid the need to `\\` escape within the string. `gpylint` enforces
|
||||||
this.
|
this.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
Python('Why are you hiding your eyes?')
|
Python('Why are you hiding your eyes?')
|
||||||
Gollum("I'm scared of lint errors.")
|
Gollum("I'm scared of lint errors.")
|
||||||
Narrator('"Good!" thought a happy Python reviewer.')
|
Narrator('"Good!" thought a happy Python reviewer.')
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No:
|
No:
|
||||||
Python("Why are you hiding your eyes?")
|
Python("Why are you hiding your eyes?")
|
||||||
Gollum('The lint. It burns. It burns us.')
|
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
|
often cleaner to use implicit line joining since multi-line strings do not flow
|
||||||
with the indentation of the rest of the program:
|
with the indentation of the rest of the program:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
print("This is much nicer.\n"
|
print("This is much nicer.\n"
|
||||||
"Do it this way.\n")
|
"Do it this way.\n")
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No:
|
No:
|
||||||
print("""This is pretty ugly.
|
print("""This is pretty ugly.
|
||||||
Don't do this.
|
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"
|
The preferred way to manage files is using the ["with"
|
||||||
statement](http://docs.python.org/reference/compound_stmts.html#the-with-statement):
|
statement](http://docs.python.org/reference/compound_stmts.html#the-with-statement):
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
with open("hello.txt") as hello_file:
|
with open("hello.txt") as hello_file:
|
||||||
for line in hello_file:
|
for line in hello_file:
|
||||||
print(line)
|
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
|
For file-like objects that do not support the "with" statement, use
|
||||||
`contextlib.closing()`:
|
`contextlib.closing()`:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
with contextlib.closing(urllib.urlopen("http://www.python.org/")) as front_page:
|
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
|
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.
|
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(kl@gmail.com): Use a "*" here for string repetition.
|
||||||
# TODO(Zeke) Change this to use relations.
|
# TODO(Zeke) Change this to use relations.
|
||||||
```
|
```
|
||||||
|
@ -1907,12 +1907,12 @@ Imports should be on separate lines.
|
||||||
|
|
||||||
E.g.:
|
E.g.:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes: import os
|
Yes: import os
|
||||||
import sys
|
import sys
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No: import os, sys
|
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:
|
1. Python standard library imports. For example:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
import sys
|
import sys
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1931,7 +1931,7 @@ grouped with the order being most generic to least generic:
|
||||||
module or package imports. For example:
|
module or package imports. For example:
|
||||||
|
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
import tensorflow as tf
|
import tensorflow as tf
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1939,7 +1939,7 @@ grouped with the order being most generic to least generic:
|
||||||
sub-package imports. For example:
|
sub-package imports. For example:
|
||||||
|
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
from otherproject.ai import mind
|
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:
|
sub-package as this file. For example:
|
||||||
|
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
from myproject.backend.hgwells import time_machine
|
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
|
according to each module's full package path. Code may optionally place a blank
|
||||||
line between import sections.
|
line between import sections.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
import collections
|
import collections
|
||||||
import queue
|
import queue
|
||||||
import sys
|
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
|
`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`.
|
you can only do so with an `if` if there is no `else`.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
|
|
||||||
if foo: bar(foo)
|
if foo: bar(foo)
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No:
|
No:
|
||||||
|
|
||||||
if foo: bar(foo)
|
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
|
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.
|
program so that the main program is not executed when the module is imported.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
def main():
|
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".
|
After annotating, many function signatures will become "one parameter per line".
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
def my_method(self,
|
def my_method(self,
|
||||||
first_var: int,
|
first_var: int,
|
||||||
second_var: Foo,
|
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,
|
names and type annotations. However, if everything fits on the same line,
|
||||||
go for it.
|
go for it.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
def my_method(self, first_var: int) -> int:
|
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
|
If the combination of the function name, the last parameter, and the return type
|
||||||
is too long, indent by 4 in a new line.
|
is too long, indent by 4 in a new line.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
def my_method(
|
def my_method(
|
||||||
self, first_var: int) -> Tuple[MyLongType1, MyLongType1]:
|
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
|
preferred way is to indent the parameters by 4 on a new line and align the
|
||||||
closing parenthesis with the def.
|
closing parenthesis with the def.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
def my_method(
|
def my_method(
|
||||||
self, **kw_args: Optional[MyLongType]
|
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
|
`pylint` allows you to move the closing parenthesis to a new line and align
|
||||||
with the opening one, but this is less readable.
|
with the opening one, but this is less readable.
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No:
|
No:
|
||||||
def my_method(self,
|
def my_method(self,
|
||||||
**kw_args: Optional[MyLongType]
|
**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
|
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).
|
too long to be on a single line (try to keep sub-types unbroken).
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
def my_method(
|
def my_method(
|
||||||
self,
|
self,
|
||||||
first_var: Tuple[List[MyLongType1],
|
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
|
[alias](#typing-aliases) for the type. The last resort is to break after the
|
||||||
colon and indent by 4.
|
colon and indent by 4.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
def my_function(
|
def my_function(
|
||||||
long_variable_name:
|
long_variable_name:
|
||||||
|
@ -2344,7 +2344,7 @@ def my_function(
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
No:
|
No:
|
||||||
def my_function(
|
def my_function(
|
||||||
long_variable_name: long_module_name.
|
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
|
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.
|
class that is defined below -- use a string for the class name.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
class MyClass(object):
|
class MyClass(object):
|
||||||
|
|
||||||
def __init__(self,
|
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
|
the = sign (but only for those arguments that have both an annotation and a
|
||||||
default).
|
default).
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
def func(a: int = 0) -> int:
|
def func(a: int = 0) -> int:
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
```python {.bad}
|
```python
|
||||||
No:
|
No:
|
||||||
def func(a:int=0) -> int:
|
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`,
|
484 allowed `a: Text = None` to be interpretted as `a: Optional[Text] = None`,
|
||||||
but that is no longer the preferred behavior.
|
but that is no longer the preferred behavior.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
Yes:
|
Yes:
|
||||||
def func(a: Optional[Text], b: Optional[Text] = None) -> Text:
|
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:
|
No:
|
||||||
def nullable_union(a: Union[None, Text]) -> Text:
|
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:
|
For example, if the name of module together with the type is too long:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
SomeType = module_with_long_name.TypeWithLongName
|
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):
|
`pytype` has a disable option for specific errors (similar to lint):
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
# pytype: disable=attribute-error
|
# 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
|
If an internal variable has a type that is hard or impossible to infer, you can
|
||||||
supply it as a special comment:
|
supply it as a special comment:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
a = SomeUndecoratedFunction() # type: Foo
|
a = SomeUndecoratedFunction() # type: Foo
|
||||||
```
|
```
|
||||||
<a id="s3.19.9-tuples"></a>
|
<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
|
repeated type or a set number of elements with different types. The latter is
|
||||||
commonly used as return type from a function.
|
commonly used as return type from a function.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
a = [1, 2, 3] # type: List[int]
|
a = [1, 2, 3] # type: List[int]
|
||||||
b = (1, 2, 3) # type: Tuple[int, ...]
|
b = (1, 2, 3) # type: Tuple[int, ...]
|
||||||
c = (1, "2", 3.5) # type: Tuple[int, Text, float]
|
c = (1, "2", 3.5) # type: Tuple[int, Text, float]
|
||||||
|
@ -2482,7 +2482,7 @@ function `TypeVar` is a common way to use them.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
from typing import List, TypeVar
|
from typing import List, TypeVar
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
...
|
...
|
||||||
|
@ -2492,7 +2492,7 @@ def next(l: List[T]) -> T:
|
||||||
|
|
||||||
A TypeVar can be constrained:
|
A TypeVar can be constrained:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
AddableType = TypeVar("AddableType", int, float, Text)
|
AddableType = TypeVar("AddableType", int, float, Text)
|
||||||
def add(a: AddableType, b: AddableType) -> AddableType:
|
def add(a: AddableType, b: AddableType) -> AddableType:
|
||||||
return a + b
|
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
|
multiple annotations that can be `bytes` or `unicode` and must all be the same
|
||||||
type.
|
type.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
from typing import AnyStr
|
from typing import AnyStr
|
||||||
def check_length(x: AnyStr) -> AnyStr:
|
def check_length(x: AnyStr) -> AnyStr:
|
||||||
if len(x) <= 42:
|
if len(x) <= 42:
|
||||||
|
@ -2514,40 +2514,55 @@ def check_length(x: AnyStr) -> AnyStr:
|
||||||
<a id="typing-strings"></a>
|
<a id="typing-strings"></a>
|
||||||
#### 3.19.11 Strings types
|
#### 3.19.11 Strings types
|
||||||
|
|
||||||
When annotating functions that take or return strings, avoid using `str`,
|
The proper type for annotating strings depends on what versions of Python the
|
||||||
because it means different things in Python 2 and Python 3. In Python 2, `str`
|
code is intended for.
|
||||||
is `bytes`; in Python 3, it is `unicode`. Whenever possible, it is best to be
|
|
||||||
explicit:
|
|
||||||
|
|
||||||
```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:
|
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}
|
```python
|
||||||
def f(x: bytes) -> bytes:
|
def deals_with_binary_data(x: bytes) -> bytes:
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
For code that processes text data (`str` or `unicode` in Python 2, `str` in
|
For Python 2 compatible code that processes text data (`str` or `unicode` in
|
||||||
Python 3), use `Text`.
|
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
|
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
|
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
|
explicitly allowed to import multiple specific classes on one line from the
|
||||||
`typing` module. Ex:
|
`typing` module. Ex:
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
from typing import Any, Dict, Optional
|
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
|
between a type and an existing name in a module, import it using
|
||||||
`import x as y`.
|
`import x as y`.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
from typing import Any as AnyType
|
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.
|
- There should be no empty lines in the typing imports list.
|
||||||
- Sort this list as if it were a regular imports list.
|
- Sort this list as if it were a regular imports list.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
import typing
|
import typing
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
import sketch
|
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
|
this module (any attribute of Any is Any). Alias definitions should be separated
|
||||||
from the last import by one line.
|
from the last import by one line.
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
some_mod = Any # some_mod.py imports this module.
|
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,
|
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).
|
[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]:
|
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]
|
# These are both interpreted as get_names(employee_ids: List[Any]) -> Dict[Any, Any]
|
||||||
def get_names(employee_ids: list) -> Dict:
|
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
|
remember that in many cases [`TypeVar`](#typing-type-var) might be more
|
||||||
appropriate:
|
appropriate:
|
||||||
|
|
||||||
```python {.bad}
|
```python
|
||||||
def get_names(employee_ids: List[Any]) -> Dict[Any, Text]:
|
def get_names(employee_ids: List[Any]) -> Dict[Any, Text]:
|
||||||
"""Returns a mapping from employee ID to employee name for given IDs."""
|
"""Returns a mapping from employee ID to employee name for given IDs."""
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {.good}
|
```python
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
def get_names(employee_ids: List[T]) -> Dict[T, Text]:
|
def get_names(employee_ids: List[T]) -> Dict[T, Text]:
|
||||||
"""Returns a mapping from employee ID to employee name for given IDs."""
|
"""Returns a mapping from employee ID to employee name for given IDs."""
|
||||||
|
|
Loading…
Reference in New Issue
Block a user