diff --git a/pyguide.md b/pyguide.md
index 0448d68..09df969 100644
--- a/pyguide.md
+++ b/pyguide.md
@@ -212,9 +212,10 @@ that the arguments are actually unused.
### 2.2 Imports
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),
-and the
+and redirects from the
[six.moves module](https://six.readthedocs.io/#module-six.moves)
are exempt from this rule.
@@ -324,7 +325,7 @@ Yes:
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
No:
@@ -440,6 +441,7 @@ Exceptions must follow certain conditions:
return port
```
+
- Libraries or packages may define their own exceptions. When doing so they
must inherit from an existing exception class. Exception names should end in
`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
Properties may be used to control getting or setting attributes that require
-trivial, but unsurprising, computations or logic. Property implementations must
-match the general expectations of regular attribute access: that they are cheap,
-straightforward, and unsurprising.
+trivial computations or logic. Property implementations must match the general
+expectations of regular attribute access: that they are cheap, straightforward,
+and unsurprising.
@@ -981,7 +983,7 @@ straightforward, and unsurprising.
#### 2.13.1 Definition
A way to wrap method calls for getting and setting an attribute as a standard
-attribute access when the computation is lightweight.
+attribute access.
@@ -989,12 +991,12 @@ attribute access when the computation is lightweight.
#### 2.13.2 Pros
-Readability is increased by eliminating explicit get and set method calls for
-simple attribute access. Allows calculations to be lazy. Considered the Pythonic
-way to maintain the interface of a class. In terms of performance, allowing
-properties bypasses needing trivial accessor methods when a direct variable
-access is reasonable. This also allows accessor methods to be added in the
-future without breaking the interface.
+* Allows for an attribute access and assignment API rather than
+ [getter and setter](#getters-and-setters) method calls.
+* Can be used to make an attribute read-only.
+* Allows calculations to be lazy.
+* Provides a way to maintain the public interface of a class when the
+ internals evolve independently of class users.
@@ -1002,8 +1004,8 @@ future without breaking the interface.
#### 2.13.3 Cons
-Can hide side-effects much like operator overloading. Can be confusing for
-subclasses.
+* Can hide side-effects much like operator overloading.
+* Can be confusing for subclasses.
@@ -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
isn't allowed: there is no computation occurring, so the property is unnecessary
-([make it public instead](#getters-and-setters)). In comparison, using a
-property to control attribute access, or calculate a *trivially* derived value,
-is allowed: the logic is trivial, but unsurprising.
+([make the attribute public instead](#getters-and-setters)). In comparison,
+using a property to control attribute access or to calculate a *trivially*
+derived value is allowed: the logic is simple and unsurprising.
Properties should be created with the `@property`
[decorator](#s2.17-function-and-method-decorators). Manually implementing a
property descriptor is considered a [power feature](#power-features).
-Inheritance with properties can be non-obvious if the property itself is not
-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 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
-```
+Inheritance with properties can be non-obvious. Do not use properties to
+implement computations a subclass may ever want to override and extend.
@@ -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 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`).
+
@@ -1290,8 +1250,9 @@ eliminate some repetitive code, enforce invariants, etc.
Decorators can perform arbitrary operations on a function's arguments or return
values, resulting in surprising implicit behavior. Additionally, decorators
-execute at import time. Failures in decorator code are pretty much impossible to
-recover from.
+execute at object definition time. For module-level objects (classes, module
+functions, ...) this happens at import time. Failures in decorator code are
+pretty much impossible to recover from.
@@ -1885,7 +1846,7 @@ No: x<1
Never use spaces around `=` when passing keyword arguments or defining a default
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.
```python
@@ -1955,7 +1916,7 @@ inline comments.
#### 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
extracted automatically through the `__doc__` member of the object and are used
by `pydoc`.
@@ -2083,7 +2044,7 @@ aptly described using a one-line docstring.
def fetch_smalltable_rows(table_handle: smalltable.Table,
keys: Sequence[Union[bytes, str]],
require_all_keys: bool = False,
-) -> Mapping[bytes, Tuple[str]]:
+) -> Mapping[bytes, Tuple[str, ...]]:
"""Fetches rows from a Smalltable.
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,
keys: Sequence[Union[bytes, str]],
require_all_keys: bool = False,
-) -> Mapping[bytes, Tuple[str]]:
+) -> Mapping[bytes, Tuple[str, ...]]:
"""Fetches rows from a Smalltable.
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 --
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
+from __future__ import annotations
+
class MyClass:
- def __init__(self,
- stack: List["MyClass"]) -> None:
+ def __init__(self, stack: Sequence[MyClass]) -> None:
```
@@ -3120,7 +3083,7 @@ class MyClass:
As per
[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.
```python