mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
Merge pull request #692 from google/python_styleguide
Project import generated by Copybara.
This commit is contained in:
commit
a5197abff2
157
pyguide.md
157
pyguide.md
|
@ -212,12 +212,7 @@ that the arguments are actually unused.
|
||||||
### 2.2 Imports
|
### 2.2 Imports
|
||||||
|
|
||||||
Use `import` statements for packages and modules only, not for individual
|
Use `import` statements for packages and modules only, not for individual
|
||||||
classes or functions. Classes imported from the
|
classes or functions.
|
||||||
[`typing` module](#typing-imports), [`collections.abc` module](#typing-imports),
|
|
||||||
[`typing_extensions` module](https://github.com/python/typing/tree/master/typing_extensions),
|
|
||||||
and redirects from the
|
|
||||||
[six.moves module](https://six.readthedocs.io/#module-six.moves)
|
|
||||||
are exempt from this rule.
|
|
||||||
|
|
||||||
<a id="s2.2.1-definition"></a>
|
<a id="s2.2.1-definition"></a>
|
||||||
<a id="221-definition"></a>
|
<a id="221-definition"></a>
|
||||||
|
@ -272,6 +267,18 @@ Do not use relative names in imports. Even if the module is in the same package,
|
||||||
use the full package name. This helps prevent unintentionally importing a
|
use the full package name. This helps prevent unintentionally importing a
|
||||||
package twice.
|
package twice.
|
||||||
|
|
||||||
|
<a id="imports-exemptions"></a>
|
||||||
|
##### 2.2.4.1 Exemptions
|
||||||
|
|
||||||
|
Exemptions from this rule:
|
||||||
|
|
||||||
|
* Classes imported from the [`typing` module](#typing-imports).
|
||||||
|
* Classes imported from the [`collections.abc` module](#typing-imports).
|
||||||
|
* Classes imported from the
|
||||||
|
[`typing_extensions` module](https://github.com/python/typing/tree/HEAD/typing_extensions).
|
||||||
|
* Redirects from the
|
||||||
|
[six.moves module](https://six.readthedocs.io/#module-six.moves).
|
||||||
|
|
||||||
<a id="s2.3-packages"></a>
|
<a id="s2.3-packages"></a>
|
||||||
<a id="23-packages"></a>
|
<a id="23-packages"></a>
|
||||||
|
|
||||||
|
@ -722,14 +729,12 @@ Yes: for key in adict: ...
|
||||||
if obj in alist: ...
|
if obj in alist: ...
|
||||||
for line in afile: ...
|
for line in afile: ...
|
||||||
for k, v in adict.items(): ...
|
for k, v in adict.items(): ...
|
||||||
for k, v in six.iteritems(adict): ...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```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(): ...
|
||||||
for k, v in dict.iteritems(): ...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<a id="s2.9-generators"></a>
|
<a id="s2.9-generators"></a>
|
||||||
|
@ -744,7 +749,7 @@ Use generators as needed.
|
||||||
<a id="291-definition"></a>
|
<a id="291-definition"></a>
|
||||||
|
|
||||||
<a id="generators-definition"></a>
|
<a id="generators-definition"></a>
|
||||||
#### 2.9 Definition
|
#### 2.9.1 Definition
|
||||||
|
|
||||||
A generator function returns an iterator that yields a value each time it
|
A generator function returns an iterator that yields a value each time it
|
||||||
executes a yield statement. After it yields a value, the runtime state of the
|
executes a yield statement. After it yields a value, the runtime state of the
|
||||||
|
@ -766,7 +771,8 @@ creates an entire list of values at once.
|
||||||
<a id="generators-cons"></a>
|
<a id="generators-cons"></a>
|
||||||
#### 2.9.3 Cons
|
#### 2.9.3 Cons
|
||||||
|
|
||||||
None.
|
Local variables in the generator will not be garbage collected until the
|
||||||
|
generator is either consumed to exhaustion or itself garbage collected.
|
||||||
|
|
||||||
<a id="s2.9.4-decision"></a>
|
<a id="s2.9.4-decision"></a>
|
||||||
<a id="294-decision"></a>
|
<a id="294-decision"></a>
|
||||||
|
@ -777,6 +783,11 @@ None.
|
||||||
Fine. Use "Yields:" rather than "Returns:" in the docstring for generator
|
Fine. Use "Yields:" rather than "Returns:" in the docstring for generator
|
||||||
functions.
|
functions.
|
||||||
|
|
||||||
|
If the generator manages an expensive resource, make sure to force the clean up.
|
||||||
|
|
||||||
|
A good way to do the clean up is by wrapping the generator with a context
|
||||||
|
manager [PEP-0533](https://peps.python.org/pep-0533/).
|
||||||
|
|
||||||
<a id="s2.10-lambda-functions"></a>
|
<a id="s2.10-lambda-functions"></a>
|
||||||
<a id="210-lambda-functions"></a>
|
<a id="210-lambda-functions"></a>
|
||||||
|
|
||||||
|
@ -1415,14 +1426,6 @@ In code that may execute on versions as old as 3.5 rather than >= 3.7, import:
|
||||||
from __future__ import generator_stop
|
from __future__ import generator_stop
|
||||||
```
|
```
|
||||||
|
|
||||||
For legacy code with the burden of continuing to support 2.7, import:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import division
|
|
||||||
from __future__ import print_function
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information read the
|
For more information read the
|
||||||
[Python future statement definitions](https://docs.python.org/3/library/__future__.html)
|
[Python future statement definitions](https://docs.python.org/3/library/__future__.html)
|
||||||
documentation.
|
documentation.
|
||||||
|
@ -1433,19 +1436,7 @@ feature a specific future import enables in your code today, keeping it in place
|
||||||
in the file prevents later modifications of the code from inadvertently
|
in the file prevents later modifications of the code from inadvertently
|
||||||
depending on the older behavior.
|
depending on the older behavior.
|
||||||
|
|
||||||
Use other `from __future__` import statements as you see fit. We did not include
|
Use other `from __future__` import statements as you see fit.
|
||||||
`unicode_literals` in our recommendations for 2.7 as it was not a clear win due
|
|
||||||
to implicit default codec conversion consequences it introduced in many places
|
|
||||||
within 2.7. Most dual-version 2-and-3 code was better off with explicit use of
|
|
||||||
`b''` and `u''` bytes and unicode string literals where necessary.
|
|
||||||
|
|
||||||
##### The six, future, and past libraries
|
|
||||||
|
|
||||||
When your project still needs to support use under both Python 2 and 3, use the
|
|
||||||
[six](https://pypi.org/project/six/),
|
|
||||||
[future](https://pypi.org/project/future/), and
|
|
||||||
[past](https://pypi.org/project/past/) libraries as you see fit. They exist to
|
|
||||||
make your code cleaner and life easier.
|
|
||||||
|
|
||||||
<a id="s2.21-type-annotated-code"></a>
|
<a id="s2.21-type-annotated-code"></a>
|
||||||
<a id="s2.21-typed-code"></a>
|
<a id="s2.21-typed-code"></a>
|
||||||
|
@ -1455,11 +1446,10 @@ make your code cleaner and life easier.
|
||||||
<a id="typed-code"></a>
|
<a id="typed-code"></a>
|
||||||
### 2.21 Type Annotated Code
|
### 2.21 Type Annotated Code
|
||||||
|
|
||||||
You can annotate Python 3 code with type hints according to
|
You can annotate Python code with type hints according to
|
||||||
[PEP-484](https://www.python.org/dev/peps/pep-0484/), and type-check the code at
|
[PEP-484](https://www.python.org/dev/peps/pep-0484/), and type-check the code at
|
||||||
build time with a type checking tool like [pytype](https://github.com/google/pytype).
|
build time with a type checking tool like [pytype](https://github.com/google/pytype).
|
||||||
|
|
||||||
|
|
||||||
Type annotations can be in the source or in a
|
Type annotations can be in the source or in a
|
||||||
[stub pyi file](https://www.python.org/dev/peps/pep-0484/#stub-files). Whenever
|
[stub pyi file](https://www.python.org/dev/peps/pep-0484/#stub-files). Whenever
|
||||||
possible, annotations should be in the source. Use pyi files for third-party or
|
possible, annotations should be in the source. Use pyi files for third-party or
|
||||||
|
@ -2129,8 +2119,8 @@ If your class has public attributes, they should be documented here in an
|
||||||
class SampleClass:
|
class SampleClass:
|
||||||
"""Summary of class here.
|
"""Summary of class here.
|
||||||
|
|
||||||
Longer class information....
|
Longer class information...
|
||||||
Longer class information....
|
Longer class information...
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
likes_spam: A boolean indicating if we like SPAM or not.
|
likes_spam: A boolean indicating if we like SPAM or not.
|
||||||
|
@ -2146,6 +2136,34 @@ class SampleClass:
|
||||||
"""Performs operation blah."""
|
"""Performs operation blah."""
|
||||||
```
|
```
|
||||||
|
|
||||||
|
All class docstrings should start with a one-line summary that describes what
|
||||||
|
the class instance represents. This implies that subclasses of `Exception`
|
||||||
|
should also describe what the exception represents, and not the context in which
|
||||||
|
it might occur. The class docstring should not repeat unnecessary information,
|
||||||
|
such as that the class is a class.
|
||||||
|
|
||||||
|
```python
|
||||||
|
class CheeseShopAddress:
|
||||||
|
"""The address of a cheese shop.
|
||||||
|
|
||||||
|
...
|
||||||
|
"""
|
||||||
|
|
||||||
|
class OutOfCheeseError(Exception):
|
||||||
|
"""No more cheese is available."""
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
class CheeseShopAddress:
|
||||||
|
"""Class that describes the address of a cheese shop.
|
||||||
|
|
||||||
|
...
|
||||||
|
"""
|
||||||
|
|
||||||
|
class OutOfCheeseError(Exception):
|
||||||
|
"""Raised when no more cheese is available."""
|
||||||
|
```
|
||||||
|
|
||||||
<a id="s3.8.5-block-and-inline-comments"></a>
|
<a id="s3.8.5-block-and-inline-comments"></a>
|
||||||
<a id="comments-in-block-and-inline"></a>
|
<a id="comments-in-block-and-inline"></a>
|
||||||
<a id="s3.8.5-comments-in-block-and-inline"></a>
|
<a id="s3.8.5-comments-in-block-and-inline"></a>
|
||||||
|
@ -2542,9 +2560,7 @@ grouped from most generic to least generic:
|
||||||
1. Python future import statements. For example:
|
1. Python future import statements. For example:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from __future__ import absolute_import
|
from __future__ import annotations
|
||||||
from __future__ import division
|
|
||||||
from __future__ import print_function
|
|
||||||
```
|
```
|
||||||
|
|
||||||
See [above](#from-future-imports) for more information about those.
|
See [above](#from-future-imports) for more information about those.
|
||||||
|
@ -2945,13 +2961,23 @@ the function into smaller and more manageable pieces.
|
||||||
|
|
||||||
* Familiarize yourself with
|
* Familiarize yourself with
|
||||||
[PEP-484](https://www.python.org/dev/peps/pep-0484/).
|
[PEP-484](https://www.python.org/dev/peps/pep-0484/).
|
||||||
|
|
||||||
* In methods, only annotate `self`, or `cls` if it is necessary for proper
|
* In methods, only annotate `self`, or `cls` if it is necessary for proper
|
||||||
type information. e.g., `@classmethod def create(cls: Type[T]) -> T: return
|
type information. e.g.,
|
||||||
cls()`
|
|
||||||
|
```python
|
||||||
|
@classmethod
|
||||||
|
def create(cls: Type[T]) -> T:
|
||||||
|
return cls()
|
||||||
|
```
|
||||||
|
|
||||||
* Similarly, don't feel compelled to annotate the return value of `__init__`
|
* Similarly, don't feel compelled to annotate the return value of `__init__`
|
||||||
(where `None` is the only valid option).
|
(where `None` is the only valid option).
|
||||||
|
|
||||||
* If any other variable or a returned type should not be expressed, use `Any`.
|
* If any other variable or a returned type should not be expressed, use `Any`.
|
||||||
|
|
||||||
* You are not required to annotate all the functions in a module.
|
* You are not required to annotate all the functions in a module.
|
||||||
|
|
||||||
- At least annotate your public APIs.
|
- At least annotate your public APIs.
|
||||||
- Use judgment to get to a good balance between safety and clarity on the
|
- Use judgment to get to a good balance between safety and clarity on the
|
||||||
one hand, and flexibility on the other.
|
one hand, and flexibility on the other.
|
||||||
|
@ -3245,8 +3271,7 @@ def add(a: AddableType, b: AddableType) -> AddableType:
|
||||||
```
|
```
|
||||||
|
|
||||||
A common predefined type variable in the `typing` module is `AnyStr`. Use it for
|
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 `str` and must all be the same type.
|
||||||
type.
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from typing import AnyStr
|
from typing import AnyStr
|
||||||
|
@ -3283,46 +3308,16 @@ No:
|
||||||
<a id="typing-strings"></a>
|
<a id="typing-strings"></a>
|
||||||
#### 3.19.11 String types
|
#### 3.19.11 String types
|
||||||
|
|
||||||
The proper type for annotating strings depends on what versions of Python the
|
> Do not use `typing.Text` in new code. It's only for Python 2/3 compatibility.
|
||||||
code is intended for.
|
|
||||||
|
|
||||||
Prefer to use `str`, though `Text` is also acceptable. Be consistent in using
|
Use `str` for string/text data. For code that deals with binary data, use
|
||||||
one or the other. For code that deals with binary data, use `bytes`. For Python
|
`bytes`.
|
||||||
2 compatible code that processes text data (`str` or `unicode` in Python 2,
|
|
||||||
`str` in Python 3), use `Text`.
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def deals_with_text_data_in_py3(x: str) -> str:
|
def deals_with_text_data(x: str) -> str:
|
||||||
...
|
...
|
||||||
def deals_with_binary_data(x: bytes) -> bytes:
|
def deals_with_binary_data(x: bytes) -> bytes:
|
||||||
...
|
...
|
||||||
def py2_compatible_text_data_processor(x: Text) -> Text:
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
In some uncommon Python 2 compatibility cases, `str` may make sense instead of
|
|
||||||
`Text`, typically to aid compatibility when the return types aren't the same
|
|
||||||
between Python 2 and Python 3. Never use `unicode` as it doesn't exist in Python
|
|
||||||
3. The reason this discrepancy exists is because `str` means something different
|
|
||||||
in Python 2 than in Python 3.
|
|
||||||
|
|
||||||
No:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def py2_code(x: str) -> unicode:
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
If the type can be either bytes or text, use `Union`, with the appropriate text
|
|
||||||
type.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from typing import Text, Union
|
|
||||||
...
|
|
||||||
def py3_only(x: Union[bytes, str]) -> Union[bytes, str]:
|
|
||||||
...
|
|
||||||
def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]:
|
|
||||||
...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If all the string types of a function are always the same, for example if the
|
If all the string types of a function are always the same, for example if the
|
||||||
|
@ -3336,11 +3331,11 @@ return type is the same as the argument type in the code above, use
|
||||||
<a id="typing-imports"></a>
|
<a id="typing-imports"></a>
|
||||||
#### 3.19.12 Imports For Typing
|
#### 3.19.12 Imports For Typing
|
||||||
|
|
||||||
For classes from the `typing` and `collections.abc` modules for use in
|
For symbols from the `typing` and `collections.abc` modules used to support
|
||||||
annotations, always import the class itself. This keeps common annotations more
|
static analysis and type checking, always import the symbol itself. This keeps
|
||||||
concise and matches typing practices used around the world. You are explicitly
|
common annotations more concise and matches typing practices used around the
|
||||||
allowed to import multiple specific classes on one line from the `typing` and
|
world. You are explicitly allowed to import multiple specific classes on one
|
||||||
`collections.abc` modules. Ex:
|
line from the `typing` and `collections.abc` modules. Ex:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from collections.abc import Mapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
|
|
Loading…
Reference in New Issue
Block a user