Movatterモバイル変換


[0]ホーム

URL:


Following system colour schemeSelected dark colour schemeSelected light colour scheme

Python Enhancement Proposals

PEP 3107 – Function Annotations

Author:
Collin Winter <collinwinter at google.com>,Tony Lownds <tony at lownds.com>
Status:
Final
Type:
Standards Track
Created:
02-Dec-2006
Python-Version:
3.0
Post-History:


Table of Contents

Abstract

This PEP introduces a syntax for adding arbitrary metadata annotationsto Python functions[1].

Rationale

Because Python’s 2.x series lacks a standard way of annotating afunction’s parameters and return values, a variety of toolsand libraries have appeared to fill this gap. Someutilise the decorators introduced inPEP 318, while others parse afunction’s docstring, looking for annotations there.

This PEP aims to provide a single, standard way of specifying thisinformation, reducing the confusion caused by the wide variation inmechanism and syntax that has existed until this point.

Fundamentals of Function Annotations

Before launching into a discussion of the precise ins and outs ofPython 3.0’s function annotations, let’s first talk broadly aboutwhat annotations are and are not:

  1. Function annotations, both for parameters and return values, arecompletely optional.
  2. Function annotations are nothing more than a way of associatingarbitrary Python expressions with various parts of a function atcompile-time.

    By itself, Python does not attach any particular meaning orsignificance to annotations. Left to its own, Python simply makesthese expressions available as described inAccessing FunctionAnnotations below.

    The only way that annotations take on meaning is when they areinterpreted by third-party libraries. These annotation consumerscan do anything they want with a function’s annotations. Forexample, one library might use string-based annotations to provideimproved help messages, like so:

    defcompile(source:"something compilable",filename:"where the compilable thing comes from",mode:"is this a single statement or a suite?"):...

    Another library might be used to provide typechecking for Pythonfunctions and methods. This library could use annotations toindicate the function’s expected input and return types, possiblysomething like:

    defhaul(item:Haulable,*vargs:PackAnimal)->Distance:...

    However, neither the strings in the first example nor thetype information in the second example have any meaning on theirown; meaning comes from third-party libraries alone.

  3. Following from point 2, this PEP makes no attempt to introduceany kind of standard semantics, even for the built-in types.This work will be left to third-party libraries.

Syntax

Parameters

Annotations for parameters take the form of optional expressions thatfollow the parameter name:

deffoo(a:expression,b:expression=5):...

In pseudo-grammar, parameters now look likeidentifier[:expression][=expression]. That is, annotations always precede aparameter’s default value and both annotations and default values areoptional. Just like how equal signs are used to indicate a defaultvalue, colons are used to mark annotations. All annotationexpressions are evaluated when the function definition is executed,just like default values.

Annotations for excess parameters (i.e.,*args and**kwargs)are indicated similarly:

deffoo(*args:expression,**kwargs:expression):...

Annotations for nested parameters always follow the name of theparameter, not the last parenthesis. Annotating all parameters of anested parameter is not required:

deffoo((x1,y1:expression),(x2:expression,y2:expression)=(None,None)):...

Return Values

The examples thus far have omitted examples of how to annotate thetype of a function’s return value. This is done like so:

defsum()->expression:...

That is, the parameter list can now be followed by a literal->and a Python expression. Like the annotations for parameters, thisexpression will be evaluated when the function definition is executed.

The grammar for function definitions[11] is now:

decorator:'@'dotted_name['('[arglist]')']NEWLINEdecorators:decorator+funcdef:[decorators]'def'NAMEparameters['->'test]':'suiteparameters:'('[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 oflambda could be changed to support annotations, by requiringparentheses around the parameter list. However it was decided[12] not to make this change because:

  1. It would be an incompatible change.
  2. Lambdas 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 thefunction’s__annotations__ attribute. This attribute isa mutable dictionary, mapping parameter names to an objectrepresenting the evaluated annotation expression

There is a special key in the__annotations__ mapping,"return". This key is present only if an annotation was suppliedfor the function’s return value.

For example, the following annotation:

deffoo(a:'x',b:5+6,c:list)->max(2,9):...

would result in an__annotations__ mapping of

{'a':'x','b':11,'c':list,'return':9}

Thereturn key was chosen because it cannot conflict with the nameof a parameter; any attempt to usereturn as a parameter namewould result in aSyntaxError.

__annotations__ is an empty, mutable dictionary if there are noannotations on the function or if the functions was created fromalambda expression.

Use Cases

In the course of discussing annotations, a number of use-cases havebeen raised. Some of these are presented here, grouped by what kindof information they convey. Also included are examples of existingproducts and packages that could make use of annotations.

  • Providing typing information
    • Type checking ([3],[4])
    • Let IDEs show what types a function expects and returns ([16])
    • Function overloading / generic functions ([21])
    • Foreign-language bridges ([17],[18])
    • Adaptation ([20],[19])
    • Predicate logic functions
    • Database query mapping
    • RPC parameter marshaling ([22])
  • Other information
    • Documentation for parameters and return values ([23])

Standard Library

pydoc and inspect

Thepydoc module should display the function annotations whendisplaying help for a function. Theinspect module should changeto support annotations.

Relation to Other PEPs

Function Signature Objects (PEP 362)

Function Signature Objects should expose the function’s annotations.TheParameter object may change or other changes may be warranted.

Implementation

A reference implementation has been checked into the py3k (formerly“p3yk”) branch as revision 53170[10].

Rejected Proposals

  • The BDFL rejected the author’s idea for a special syntax for addingannotations to generators as being “too ugly”[2].
  • Though discussed early on ([5],[6]), includingspecial objects in the stdlib for annotating generator functions andhigher-order functions was ultimately rejected as being moreappropriate for third-party libraries; including them in thestandard library raised too many thorny issues.
  • Despite considerable discussion about a standard typeparameterisation syntax, it was decided that this should also beleft to third-party libraries. ([7],[8],[9]).
  • Despite yet more discussion, it was decided not to standardizea mechanism for annotation interoperability. Standardizinginteroperability conventions at this point would be premature.We would rather let these conventions develop organically, basedon real-world usage and necessity, than try to force all usersinto some contrived scheme. ([13],[14],[15]).

References and Footnotes

[1]
Unless specifically stated, “function” is generallyused as a synonym for “callable” throughout this document.
[2]
https://mail.python.org/pipermail/python-3000/2006-May/002103.html
[3]
http://web.archive.org/web/20070730120117/http://oakwinter.com/code/typecheck/
[4]
http://web.archive.org/web/20070603221429/http://maxrepo.info/
[5]
https://mail.python.org/pipermail/python-3000/2006-May/002091.html
[6]
https://mail.python.org/pipermail/python-3000/2006-May/001972.html
[7]
https://mail.python.org/pipermail/python-3000/2006-May/002105.html
[8]
https://mail.python.org/pipermail/python-3000/2006-May/002209.html
[9]
https://mail.python.org/pipermail/python-3000/2006-June/002438.html
[10]
http://svn.python.org/view?rev=53170&view=rev
[11]
http://docs.python.org/reference/compound_stmts.html#function-definitions
[12]
https://mail.python.org/pipermail/python-3000/2006-May/001613.html
[13]
https://mail.python.org/pipermail/python-3000/2006-August/002895.html
[14]
https://mail.python.org/pipermail/python-ideas/2007-January/000032.html
[15]
https://mail.python.org/pipermail/python-list/2006-December/420645.html
[16]
http://www.python.org/idle/doc/idle2.html#Tips
[17]
http://www.jython.org/Project/index.html
[18]
http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython
[19]
http://peak.telecommunity.com/PyProtocols.html
[20]
http://www.artima.com/weblogs/viewpost.jsp?thread=155123
[21]
http://www-128.ibm.com/developerworks/library/l-cppeak2/
[22]
http://rpyc.wikispaces.com/
[23]
http://docs.python.org/library/pydoc.html

Copyright

This document has been placed in the public domain.


Source:https://github.com/python/peps/blob/main/peps/pep-3107.rst

Last modified:2025-02-01 08:59:27 GMT


[8]ページ先頭

©2009-2025 Movatter.jp