Update rules for function annotations in the light of PEP 484.
This commit is contained in:
parent
8288ff6a15
commit
146574f68a
130
pep-0008.txt
130
pep-0008.txt
|
@ -520,22 +520,33 @@ Other Recommendations
|
|||
def complex(real, imag = 0.0):
|
||||
return magic(r = real, i = imag)
|
||||
|
||||
- Do use spaces around the ``=`` sign of an annotated function definition.
|
||||
Additionally, use a single space after the ``:``, as well as a single space
|
||||
on either side of the ``->`` sign representing an annotated return value.
|
||||
- Function annotations should use the normal rules for colons and
|
||||
always have spaces around the ``->`` arrow if present. (See
|
||||
`Function Annotations`_ below for more about function annotations.)
|
||||
|
||||
Yes::
|
||||
|
||||
def munge(input: AnyStr):
|
||||
def munge(sep: AnyStr = None):
|
||||
def munge() -> AnyStr:
|
||||
def munge(input: AnyStr, sep: AnyStr = None, limit=1000):
|
||||
def munge(input: AnyStr): ...
|
||||
def munge() -> AnyStr: ...
|
||||
|
||||
No::
|
||||
|
||||
def munge(input: AnyStr=None):
|
||||
def munge(input:AnyStr):
|
||||
def munge(input: AnyStr)->PosInt:
|
||||
def munge(input:AnyStr): ...
|
||||
def munge()->PosInt: ...
|
||||
|
||||
- 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).
|
||||
|
||||
Yes::
|
||||
|
||||
def munge(sep: AnyStr = None): ...
|
||||
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
|
||||
|
||||
No::
|
||||
|
||||
def munge(input: AnyStr=None): ...
|
||||
def munge(input: AnyStr, limit = 1000): ...
|
||||
|
||||
- Compound statements (multiple statements on the same line) are
|
||||
generally discouraged.
|
||||
|
@ -1233,60 +1244,65 @@ Programming Recommendations
|
|||
No: if greeting == True:
|
||||
Worse: if greeting is True:
|
||||
|
||||
- The Python standard library will not use function annotations as
|
||||
that would result in a premature commitment to a particular
|
||||
annotation style. Instead, the annotations are left for users to
|
||||
discover and experiment with useful annotation styles.
|
||||
Function Annotations
|
||||
--------------------
|
||||
|
||||
It is recommended that third party experiments with annotations use an
|
||||
associated decorator to indicate how the annotation should be
|
||||
interpreted.
|
||||
With the acceptance of PEP 484, the style rules for function
|
||||
annotations are changing.
|
||||
|
||||
Early core developer attempts to use function annotations revealed
|
||||
inconsistent, ad-hoc annotation styles. For example:
|
||||
- In order to be forward compatible, function annotations in Python 3
|
||||
code should preferably use PEP 484 syntax. (There are some
|
||||
formatting recommendations for annotations in the previous section.)
|
||||
|
||||
* ``[str]`` was ambiguous as to whether it represented a list of
|
||||
strings or a value that could be either *str* or *None*.
|
||||
- The experimentation with annotation styles that was recommended
|
||||
previously in this PEP is no longer encouraged.
|
||||
|
||||
* The notation ``open(file:(str,bytes))`` was used for a value that
|
||||
could be either *bytes* or *str* rather than a 2-tuple containing
|
||||
a *str* value followed by a *bytes* value.
|
||||
- However, experiments within the rules of PEP 484 are now encouraged.
|
||||
For example, marking up a large library with PEP 484 style type
|
||||
annotations, reviewing how easy it was to add those annotations, and
|
||||
observing whether their presence increases code understandabilty.
|
||||
|
||||
* The annotation ``seek(whence:int)`` exhibited a mix of
|
||||
over-specification and under-specification: *int* is too
|
||||
restrictive (anything with ``__index__`` would be allowed) and it
|
||||
is not restrictive enough (only the values 0, 1, and 2 are
|
||||
allowed). Likewise, the annotation ``write(b: bytes)`` was also
|
||||
too restrictive (anything supporting the buffer protocol would be
|
||||
allowed).
|
||||
- The Python standard library should be conservative in adopting such
|
||||
annotations, but their use is allowed for new code and for big
|
||||
refactorings.
|
||||
|
||||
* Annotations such as ``read1(n: int=None)`` were self-contradictory
|
||||
since *None* is not an *int*. Annotations such as
|
||||
``source_path(self, fullname:str) -> object`` were confusing about
|
||||
what the return type should be.
|
||||
- For code that wants to make a different use of function annotations
|
||||
it is recommended to put a comment of the form::
|
||||
|
||||
* In addition to the above, annotations were inconsistent in the use
|
||||
of concrete types versus abstract types: *int* versus *Integral*
|
||||
and set/frozenset versus MutableSet/Set.
|
||||
# type: ignore
|
||||
|
||||
* Some annotations in the abstract base classes were incorrect
|
||||
specifications. For example, set-to-set operations require
|
||||
*other* to be another instance of *Set* rather than just an
|
||||
*Iterable*.
|
||||
near the top of the file; this tells type checker to ignore all
|
||||
annotations. (More fine-grained ways of disabling complaints from
|
||||
type checkers can be found in PEP 484.)
|
||||
|
||||
* A further issue was that annotations become part of the
|
||||
specification but weren't being tested.
|
||||
- Like linters, type checkers are optional, separate tools. Python
|
||||
interpreters by default should not issue any messages due to type
|
||||
checking and should not alter their behavior based on annotations.
|
||||
|
||||
* In most cases, the docstrings already included the type
|
||||
specifications and did so with greater clarity than the function
|
||||
annotations. In the remaining cases, the docstrings were improved
|
||||
once the annotations were removed.
|
||||
- Users who don't want to use type checkers are free to ignore them.
|
||||
However, it is expected that users of library packages may want to
|
||||
run type checkers over those library packages. For this purpose PEP
|
||||
484 recommends the use of stub files: .pyi files that are read by
|
||||
the type checker in preference of the corresponding .py files. Stub
|
||||
files can be distributed with a library, or separately (with the
|
||||
library author's permission) through the _typeshed_ repo [5]_.
|
||||
|
||||
* The observed function annotations were too ad-hoc and inconsistent
|
||||
to work with a coherent system of automatic type checking or
|
||||
argument validation. Leaving these annotations in the code would
|
||||
have made it more difficult to make changes later so that
|
||||
automated utilities could be supported.
|
||||
- For code that needs to be backwards compatible, function annotations
|
||||
can be added in the form of comments. Basically, this Python 3 annotation::
|
||||
|
||||
def embezzle(self, account: str, funds: int = 1000000, **fake_receipts: str) -> None:
|
||||
"""Embezzle funds from account using fake receipts."""
|
||||
<code goes here>
|
||||
|
||||
is equivalent to the following::
|
||||
|
||||
def embezzle(self, account, funds=1000000, **fake_receipts):
|
||||
# type: (str, int, **str) -> None
|
||||
"""Embezzle funds from account using fake receipts."""
|
||||
<code goes here>
|
||||
|
||||
The _mypy_ type checker [6]_ currently support this syntax, and other
|
||||
type checkers are encouraged to adopt it.
|
||||
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
@ -1312,6 +1328,14 @@ References
|
|||
.. [4] PEP 8 modernisation, July 2013
|
||||
http://bugs.python.org/issue18472
|
||||
|
||||
.. [5] Typeshed repo
|
||||
https://github.com/python/typeshed
|
||||
|
||||
.. [6] mypy type checker
|
||||
http://mypy-lang.org
|
||||
https://github.com/JukkaL/mypy
|
||||
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
|
Loading…
Reference in New Issue