Merge pull request #660 from google/python_styleguide

Project import generated by Copybara.
This commit is contained in:
Gregory P. Smith 2021-12-07 13:42:38 -08:00 committed by GitHub
commit 842b872ac4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -212,9 +212,10 @@ 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. Imports from the [typing module](#typing-imports), classes or functions. Classes imported from the
[typing module](#typing-imports),
[typing_extensions module](https://github.com/python/typing/tree/master/typing_extensions), [typing_extensions module](https://github.com/python/typing/tree/master/typing_extensions),
and the and redirects from the
[six.moves module](https://six.readthedocs.io/#module-six.moves) [six.moves module](https://six.readthedocs.io/#module-six.moves)
are exempt from this rule. are exempt from this rule.
@ -324,7 +325,7 @@ Yes:
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
``` ```
_(assume this file lives in `doctor/who/` where `jodie.py` also exists)_ *(assume this file lives in `doctor/who/` where `jodie.py` also exists)*
```python ```python
No: No:
@ -440,6 +441,7 @@ Exceptions must follow certain conditions:
return port return port
``` ```
- Libraries or packages may define their own exceptions. When doing so they - Libraries or packages may define their own exceptions. When doing so they
must inherit from an existing exception class. Exception names should end in must inherit from an existing exception class. Exception names should end in
`Error` and should not introduce repetition (`foo.FooError`). `Error` and should not introduce repetition (`foo.FooError`).
@ -970,9 +972,9 @@ No: def foo(a, b: Mapping = {}): # Could still get passed to unchecked code
### 2.13 Properties ### 2.13 Properties
Properties may be used to control getting or setting attributes that require Properties may be used to control getting or setting attributes that require
trivial, but unsurprising, computations or logic. Property implementations must trivial computations or logic. Property implementations must match the general
match the general expectations of regular attribute access: that they are cheap, expectations of regular attribute access: that they are cheap, straightforward,
straightforward, and unsurprising. and unsurprising.
<a id="s2.13.1-definition"></a> <a id="s2.13.1-definition"></a>
<a id="2131-definition"></a> <a id="2131-definition"></a>
@ -981,7 +983,7 @@ straightforward, and unsurprising.
#### 2.13.1 Definition #### 2.13.1 Definition
A way to wrap method calls for getting and setting an attribute as a standard A way to wrap method calls for getting and setting an attribute as a standard
attribute access when the computation is lightweight. attribute access.
<a id="s2.13.2-pros"></a> <a id="s2.13.2-pros"></a>
<a id="2132-pros"></a> <a id="2132-pros"></a>
@ -989,12 +991,12 @@ attribute access when the computation is lightweight.
<a id="properties-pros"></a> <a id="properties-pros"></a>
#### 2.13.2 Pros #### 2.13.2 Pros
Readability is increased by eliminating explicit get and set method calls for * Allows for an attribute access and assignment API rather than
simple attribute access. Allows calculations to be lazy. Considered the Pythonic [getter and setter](#getters-and-setters) method calls.
way to maintain the interface of a class. In terms of performance, allowing * Can be used to make an attribute read-only.
properties bypasses needing trivial accessor methods when a direct variable * Allows calculations to be lazy.
access is reasonable. This also allows accessor methods to be added in the * Provides a way to maintain the public interface of a class when the
future without breaking the interface. internals evolve independently of class users.
<a id="s2.13.3-cons"></a> <a id="s2.13.3-cons"></a>
<a id="2133-cons"></a> <a id="2133-cons"></a>
@ -1002,8 +1004,8 @@ future without breaking the interface.
<a id="properties-cons"></a> <a id="properties-cons"></a>
#### 2.13.3 Cons #### 2.13.3 Cons
Can hide side-effects much like operator overloading. Can be confusing for * Can hide side-effects much like operator overloading.
subclasses. * Can be confusing for subclasses.
<a id="s2.13.4-decision"></a> <a id="s2.13.4-decision"></a>
<a id="2134-decision"></a> <a id="2134-decision"></a>
@ -1017,62 +1019,16 @@ necessary and match the expectations of typical attribute access; follow the
For example, using a property to simply both get and set an internal attribute For example, using a property to simply both get and set an internal attribute
isn't allowed: there is no computation occurring, so the property is unnecessary isn't allowed: there is no computation occurring, so the property is unnecessary
([make it public instead](#getters-and-setters)). In comparison, using a ([make the attribute public instead](#getters-and-setters)). In comparison,
property to control attribute access, or calculate a *trivially* derived value, using a property to control attribute access or to calculate a *trivially*
is allowed: the logic is trivial, but unsurprising. derived value is allowed: the logic is simple and unsurprising.
Properties should be created with the `@property` Properties should be created with the `@property`
[decorator](#s2.17-function-and-method-decorators). Manually implementing a [decorator](#s2.17-function-and-method-decorators). Manually implementing a
property descriptor is considered a [power feature](#power-features). property descriptor is considered a [power feature](#power-features).
Inheritance with properties can be non-obvious if the property itself is not Inheritance with properties can be non-obvious. Do not use properties to
overridden. Thus one must make sure that accessor methods are called indirectly implement computations a subclass may ever want to override and extend.
to ensure methods overridden in subclasses are called by the property (using the
[template method design pattern](https://en.wikipedia.org/wiki/Template_method_pattern)).
```python
Yes: import math
class Square:
"""A square with two properties: a writable area and a read-only perimeter.
To use:
>>> sq = Square(3)
>>> sq.area
9
>>> sq.perimeter
12
>>> sq.area = 16
>>> sq.side
4
>>> sq.perimeter
16
"""
def __init__(self, side: float):
self.side = side
@property
def area(self) -> float:
"""Area of the square."""
return self._get_area()
@area.setter
def area(self, area: float):
self._set_area(area)
def _get_area(self) -> float:
"""Indirect accessor to calculate the 'area' property."""
return self.side ** 2
def _set_area(self, area: float):
"""Indirect setter to set the 'area' property."""
self.side = math.sqrt(area)
@property
def perimeter(self) -> float:
return self.side * 4
```
<a id="s2.14-truefalse-evaluations"></a> <a id="s2.14-truefalse-evaluations"></a>
<a id="214-truefalse-evaluations"></a> <a id="214-truefalse-evaluations"></a>
@ -1161,6 +1117,10 @@ Use the "implicit" false if possible, e.g., `if foo:` rather than `if foo !=
- Note that `'0'` (i.e., `0` as string) evaluates to true. - Note that `'0'` (i.e., `0` as string) evaluates to true.
- Note that Numpy arrays may raise an exception in an implicit boolean
context. Prefer the `.size` attribute when testing emptiness of a `np.array`
(e.g. `if not users.size`).
<a id="s2.16-lexical-scoping"></a> <a id="s2.16-lexical-scoping"></a>
<a id="216-lexical-scoping"></a> <a id="216-lexical-scoping"></a>
@ -1290,8 +1250,9 @@ eliminate some repetitive code, enforce invariants, etc.
Decorators can perform arbitrary operations on a function's arguments or return Decorators can perform arbitrary operations on a function's arguments or return
values, resulting in surprising implicit behavior. Additionally, decorators values, resulting in surprising implicit behavior. Additionally, decorators
execute at import time. Failures in decorator code are pretty much impossible to execute at object definition time. For module-level objects (classes, module
recover from. functions, ...) this happens at import time. Failures in decorator code are
pretty much impossible to recover from.
<a id="s2.17.4-decision"></a> <a id="s2.17.4-decision"></a>
<a id="2174-decision"></a> <a id="2174-decision"></a>
@ -1885,7 +1846,7 @@ No: x<1
Never use spaces around `=` when passing keyword arguments or defining a default Never use spaces around `=` when passing keyword arguments or defining a default
parameter value, with one exception: parameter value, with one exception:
[when a type annotation is present](#typing-default-values), _do_ use spaces [when a type annotation is present](#typing-default-values), *do* use spaces
around the `=` for the default parameter value. around the `=` for the default parameter value.
```python ```python
@ -1955,7 +1916,7 @@ inline comments.
<a id="docstrings"></a> <a id="docstrings"></a>
#### 3.8.1 Docstrings #### 3.8.1 Docstrings
Python uses _docstrings_ to document code. A docstring is a string that is the Python uses *docstrings* to document code. A docstring is a string that is the
first statement in a package, module, class or function. These strings can be first statement in a package, module, class or function. These strings can be
extracted automatically through the `__doc__` member of the object and are used extracted automatically through the `__doc__` member of the object and are used
by `pydoc`. by `pydoc`.
@ -2083,7 +2044,7 @@ aptly described using a one-line docstring.
def fetch_smalltable_rows(table_handle: smalltable.Table, def fetch_smalltable_rows(table_handle: smalltable.Table,
keys: Sequence[Union[bytes, str]], keys: Sequence[Union[bytes, str]],
require_all_keys: bool = False, require_all_keys: bool = False,
) -> Mapping[bytes, Tuple[str]]: ) -> Mapping[bytes, Tuple[str, ...]]:
"""Fetches rows from a Smalltable. """Fetches rows from a Smalltable.
Retrieves rows pertaining to the given keys from the Table instance Retrieves rows pertaining to the given keys from the Table instance
@ -2120,7 +2081,7 @@ Similarly, this variation on `Args:` with a line break is also allowed:
def fetch_smalltable_rows(table_handle: smalltable.Table, def fetch_smalltable_rows(table_handle: smalltable.Table,
keys: Sequence[Union[bytes, str]], keys: Sequence[Union[bytes, str]],
require_all_keys: bool = False, require_all_keys: bool = False,
) -> Mapping[bytes, Tuple[str]]: ) -> Mapping[bytes, Tuple[str, ...]]:
"""Fetches rows from a Smalltable. """Fetches rows from a Smalltable.
Retrieves rows pertaining to the given keys from the Table instance Retrieves rows pertaining to the given keys from the Table instance
@ -3103,13 +3064,15 @@ def my_function(
If you need to use a class name from the same module that is not yet defined -- 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 -- either use `from __future__ import annotations`
for simple cases or use a string for the class name.
```python ```python
from __future__ import annotations
class MyClass: class MyClass:
def __init__(self, def __init__(self, stack: Sequence[MyClass]) -> None:
stack: List["MyClass"]) -> None:
``` ```
<a id="s3.19.4-default-values"></a> <a id="s3.19.4-default-values"></a>
@ -3120,7 +3083,7 @@ class MyClass:
As per As per
[PEP-008](https://www.python.org/dev/peps/pep-0008/#other-recommendations), use [PEP-008](https://www.python.org/dev/peps/pep-0008/#other-recommendations), use
spaces around the `=` _only_ for arguments that have both a type annotation and spaces around the `=` *only* for arguments that have both a type annotation and
a default value. a default value.
```python ```python