Update from Tony Lownds sent in private mail and to python-3000
This commit is contained in:
parent
58bc5d3a66
commit
2cab42267d
143
pep-3107.txt
143
pep-3107.txt
|
@ -3,7 +3,7 @@ Title: Function Annotations
|
|||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: Collin Winter <collinw@gmail.com>,
|
||||
Tony Lownds <tony@pagedna.com>
|
||||
Tony Lownds <tony@lownds.com>
|
||||
Status: Draft
|
||||
Type: Standards Track
|
||||
Requires: 362
|
||||
|
@ -51,9 +51,8 @@ what annotations are and are not:
|
|||
|
||||
By itself, Python does not attach any particular meaning or
|
||||
significance to annotations. Left to its own, Python simply makes
|
||||
these expressions available as the values in the
|
||||
``__signature__.annotations`` mapping described in `Accessing
|
||||
Function Annotations`_ below.
|
||||
these expressions available as described in `Accessing Function
|
||||
Annotations`_ below.
|
||||
|
||||
The only way that annotations take on meaning is when they are
|
||||
interpreted by third-party libraries. These annotation consumers
|
||||
|
@ -98,38 +97,33 @@ Parameters
|
|||
----------
|
||||
|
||||
Annotations for parameters take the form of optional expressions that
|
||||
follow the parameter name. This example indicates that parameters 'a'
|
||||
and 'c' should both be a ``Number``, while parameter 'b' should
|
||||
be a ``Mapping``::
|
||||
follow the parameter name. This example indicates that parameters
|
||||
'a' and 'c' should both be an ``int``, while parameter 'b' should
|
||||
be a ``dict``::
|
||||
|
||||
def foo(a: Number, b: Mapping, c: Number = 5):
|
||||
def foo(a: int, b: dict, c: int = 5):
|
||||
...
|
||||
|
||||
(Number, Mapping and Sequence are used thoughout this PEP and
|
||||
represent the standard `numeric`_, `mapping`_ and `sequence
|
||||
protocols`_.)
|
||||
|
||||
In pseudo-grammar, parameters now look like ``identifier [:
|
||||
expression] [= expression]``. That is, type annotations always
|
||||
precede a parameter's default value and both type annotations and
|
||||
default values are optional. Just like how equal signs are used to
|
||||
indicate a default value, colons are used to mark annotations. All
|
||||
annotation expressions are evaluated when the function definition is
|
||||
executed.
|
||||
expression] [= expression]``. That is, annotations always precede a
|
||||
parameter's default value and both annotations and default values are
|
||||
optional. Just like how equal signs are used to indicate a default
|
||||
value, colons are used to mark annotations. All annotation
|
||||
expressions are evaluated when the function definition is executed.
|
||||
|
||||
Annotations for excess parameters (i.e., ``*args`` and ``**kwargs``)
|
||||
are indicated similarly. In the following function definition,
|
||||
``*args`` is flagged as a list of ``Number``, and ``**kwargs`` is
|
||||
``*args`` is flagged as a tuple of ``int``, and ``**kwargs`` is
|
||||
marked as a dict whose keys are strings and whose values are of type
|
||||
``Sequence``. ::
|
||||
``str``::
|
||||
|
||||
def foo(*args: Number, **kwargs: Sequence):
|
||||
def foo(*args: int, **kwargs: str):
|
||||
...
|
||||
|
||||
Note that, depending on what annotation-interpreting library you're
|
||||
using, the following might also be a valid spelling of the above::
|
||||
|
||||
def foo(*args: [Number], **kwargs: {str: Sequence}):
|
||||
def foo(*args: [int], **kwargs: {str: str}):
|
||||
...
|
||||
|
||||
Only the first, however, has the BDFL's blessing [#blessedexcess]_ as
|
||||
|
@ -142,68 +136,99 @@ Return Values
|
|||
The examples thus far have omitted examples of how to annotate the
|
||||
type of a function's return value. This is done like so::
|
||||
|
||||
def sum(*args: Number) -> Number:
|
||||
def sum(*args: int) -> int:
|
||||
...
|
||||
|
||||
The parameter list can now be followed by a literal ``->`` and a
|
||||
Python expression. Like the annotations for parameters, this
|
||||
expression will be evaluated when the function definition is executed.
|
||||
|
||||
The grammar for function definitions [#grammar]_ is now something like::
|
||||
The grammar for function definitions [#grammar]_ is now::
|
||||
|
||||
funcdef ::= [decorators] "def" funcname "("
|
||||
[parameter_list] ")" ["->" expression] ":" suite
|
||||
decorators ::= decorator+
|
||||
decorator ::= "@" dotted_name ["(" [argument_list
|
||||
[","]] ")"] NEWLINE
|
||||
dotted_name ::= identifier ("." identifier)*
|
||||
parameter_list ::= (defparameter ",")*
|
||||
( "*" identifier [":" expression]
|
||||
[, "**" identifier [":" expression] ]
|
||||
| "**" identifier [":" expression]
|
||||
| defparameter [","] )
|
||||
defparameter ::= parameter [":" expression] ["=" expression]
|
||||
sublist ::= parameter ("," parameter)* [","]
|
||||
parameter ::= identifier | "(" sublist ")"
|
||||
funcname ::= identifier
|
||||
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
|
||||
decorators: decorator+
|
||||
funcdef: [decorators] 'def' NAME parameters ['->' test] ':' suite
|
||||
parameters: '(' [typedargslist] ')'
|
||||
typedargslist: ((tfpdef ['=' test] ',')*
|
||||
('*' [tname] (',' tname ['=' test])* [',' '**' tname]
|
||||
| '**' tname)
|
||||
| tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
|
||||
tname: NAME [':' test]
|
||||
tfpdef: tname | '(' tfplist ')'
|
||||
tfplist: tfpdef (',' tfpdef)* [',']
|
||||
|
||||
Lambda
|
||||
------
|
||||
|
||||
``lambda``'s syntax does not support annotations. The syntax of
|
||||
``lambda`` could be changed to support annotations, by requiring
|
||||
parentheses around the parameter list. However it was decided
|
||||
[#lambda]_ not to make this change because:
|
||||
|
||||
1. It would be an incompatible change.
|
||||
2. Lambda's are neutered anyway.
|
||||
3. The lambda can always be changed to a function.
|
||||
|
||||
|
||||
Accessing Function Annotations
|
||||
==============================
|
||||
|
||||
Once compiled, a function's annotations are available via the
|
||||
function's ``__signature__`` attribute, introduced by PEP 362.
|
||||
Signature objects include an attribute just for annotations,
|
||||
appropriately called ``annotations``. This attribute is a dictionary,
|
||||
mapping parameter names to an object representing the evaluated
|
||||
annotation expression.
|
||||
function's ``func_annotations`` attribute. This attribute is
|
||||
a dictionary, mapping parameter names to an object representing
|
||||
the evaluated annotation expression
|
||||
|
||||
There is a special key in the ``annotations`` mapping, ``"return"``.
|
||||
This key is present only if an annotation was supplied for the
|
||||
function's return value.
|
||||
There is a special key in the ``func_annotations`` mapping,
|
||||
``"return"``. This key is present only if an annotation was supplied
|
||||
for the function's return value.
|
||||
|
||||
For example, the following annotation::
|
||||
|
||||
def foo(a: Number, b: 5 + 6, c: list) -> String:
|
||||
def foo(a: 'x', b: 5 + 6, c: list) -> str:
|
||||
...
|
||||
|
||||
would result in a ``__signature__.annotations`` mapping of ::
|
||||
would result in a ``func_annotation`` mapping of ::
|
||||
|
||||
{'a': Number,
|
||||
{'a': 'x',
|
||||
'b': 11,
|
||||
'c': list,
|
||||
'return': String}
|
||||
'return': str}
|
||||
|
||||
The ``return`` key was chosen because it cannot conflict with the name
|
||||
of a parameter; any attempt to use ``return`` as a parameter name
|
||||
would result in a ``SyntaxError``.
|
||||
|
||||
``func_annotations`` is an empty dictionary if no there are no
|
||||
annotations on the function. ``func_annotations`` is always an empty
|
||||
dictionary for functions created from ``lambda`` expressions.
|
||||
|
||||
|
||||
Standard Library
|
||||
================
|
||||
|
||||
pydoc and inspect
|
||||
-----------------
|
||||
|
||||
The ``pydoc`` module should display the function annotations when
|
||||
displaying help for a function. The ``inspect`` module should change
|
||||
to support annotations.
|
||||
|
||||
|
||||
Relation to Other PEPs
|
||||
======================
|
||||
|
||||
Function Signature Objects [#pep-362]_
|
||||
--------------------------------------
|
||||
|
||||
Function Signature Objects should expose the function's annotations.
|
||||
The ``Parameter`` object may change or other changes may be warranted.
|
||||
|
||||
|
||||
Implementation
|
||||
==============
|
||||
|
||||
A sample implementation has been provided [#implementation]_ by Tony
|
||||
Lownds.
|
||||
A sample implementation for the syntax changes has been provided
|
||||
[#implementation]_ by Tony Lownds.
|
||||
|
||||
|
||||
Rejected Proposals
|
||||
|
@ -220,8 +245,8 @@ Rejected Proposals
|
|||
|
||||
+ Despite considerable discussion about a standard type
|
||||
parameterisation syntax, it was decided that this should also be
|
||||
left to third-party libraries. ([#threadimmlist]_, [#threadmixing]_,
|
||||
[#emphasistpls]_)
|
||||
left to third-party libraries. ([#threadimmlist]_,
|
||||
[#threadmixing]_, [#emphasistpls]_)
|
||||
|
||||
|
||||
References and Footnotes
|
||||
|
@ -276,6 +301,13 @@ References and Footnotes
|
|||
.. [#grammar]
|
||||
http://www.python.org/doc/current/ref/function.html
|
||||
|
||||
.. [#lambda]
|
||||
http://mail.python.org/pipermail/python-3000/2006-May/001613.html
|
||||
|
||||
.. [#pep-362]
|
||||
http://www.python.org/dev/peps/pep-0362/
|
||||
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
@ -291,3 +323,4 @@ This document has been placed in the public domain.
|
|||
fill-column: 70
|
||||
coding: utf-8
|
||||
End:
|
||||
|
||||
|
|
Loading…
Reference in New Issue