[Python-checkins] peps (merge default -> default): Merge

brett.cannon python-checkins at python.org
Fri Mar 20 19:28:19 CET 2015


https://hg.python.org/peps/rev/71523d1c9158
changeset:   5737:71523d1c9158
parent:      5736:062ca9bdf9da
parent:      5735:4d7b657827b2
user:        Brett Cannon <brett at python.org>
date:        Fri Mar 20 14:28:14 2015 -0400
summary:
  Merge

files:
  pep-0484.txt |  551 +++++++++++++++++++++++++++++++++++---
  1 files changed, 501 insertions(+), 50 deletions(-)


diff --git a/pep-0484.txt b/pep-0484.txt
--- a/pep-0484.txt
+++ b/pep-0484.txt
@@ -8,7 +8,7 @@
 Type: Standards Track
 Content-Type: text/x-rst
 Created: 29-Sep-2014
-Post-History: 16-Jan-2015
+Post-History: 16-Jan-2015,20-Mar-2015
 Resolution:
 
 
@@ -16,11 +16,33 @@
 ========
 
 This PEP introduces a standard syntax for type hints using annotations
-on function definitions.
+(PEP 3107) on function definitions.  For example, here is a simple
+function whose argument and return type are declared in the
+annotations::
 
-The proposal is strongly inspired by mypy [mypy]_.
+  def greeting(name: str) -> str:
+      return 'Hello ' + name
 
-The theory behind type hints and gradual typing is explained in PEP 483.
+While these annotations are available at runtime through the usual
+``__annotations__`` attribute, *no type checking happens at runtime*.
+Instead, the proposal assumes the existence of a separate off-line
+type checker which users can run over their source code voluntarily.
+Essentially, such a type checker acts as a very powerful linter.
+
+The proposal is strongly inspired by mypy [mypy]_.  For example, the
+type "sequence of integers" can be written as ``Sequence[int]``.  The
+square brackets mean that no new syntax needs to be added to the
+language.  The example here uses a custom class ``Sequence``, imported
+from a pure-Python module ``typing.py``.  The ``Sequence[int]``
+notation works by implementing ``__getitem__()`` in the metaclass.
+
+The type system supports unions, generic types, and a special type
+named ``Any`` which is consistent with (i.e. assignable to and from) all
+types.  This latter feature is taken from the idea of gradual typing.
+Gradual typing and the full type system are explained in PEP 483.
+
+Other approaches from which we have borrowed or to which ours can be
+compared and contrasted are described in PEP 482.
 
 
 Rationale and Goals
@@ -36,6 +58,25 @@
 runtime type checking, and performance optimizations utilizing type
 information.
 
+Of these goals, static analysis is the most important.  This includes
+support for off-line type checkers such as mypy, as well as providing
+a standard notation that can be used by IDEs for code completion and
+refactoring.
+
+Non-goals
+---------
+
+While the proposed typing module will contain some building blocks for
+runtime type checking -- in particular a useful ``isinstance()``
+implementation -- third party packages would have to be developed to
+implement specific runtime type checking functionality, for example
+using decorators or metaclasses.  Using type hints for performance
+optimizations is left as an exercise for the reader.
+
+It should also be emphasized that Python will remain a dynamically
+typed language, and the authors have no desire to ever make type hints
+mandatory, even by convention.
+
 
 Type Definition Syntax
 ======================
@@ -70,7 +111,7 @@
 
   integer = int
 
-  def retry(url: str, retry_count: integer): ...
+  def retry(url: str, retry_count: integer) -> None: ...
 
 New names that are added to support features described in following
 sections are available in the ``typing`` package.
@@ -83,17 +124,31 @@
 type hinted using ``Callable[[Arg1Type, Arg2Type], ReturnType]``.
 Examples::
 
-  from typing import Any, AnyArgs, Callable
+  from typing import Callable
 
-  def feeder(get_next_item: Callable[[], Item]): ...
+  def feeder(get_next_item: Callable[[], str]) -> None:
+      # Body
 
-  def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]): ...
+  def async_query(on_success: Callable[[int], None],
+                  on_error: Callable[[int, Exception], None]) -> None:
+      # Body
 
-  def partial(func: Callable[AnyArgs, Any], *args): ...
+It is possible to declare the return type of a callable without
+specifying the call signature by substituting a literal ellipsis
+(three dots) for the list of arguments::
 
-Since using callbacks with keyword arguments is not perceived as
-a common use case, there is currently no support for specifying keyword
-arguments with ``Callable``.
+  def partial(func: Callable[..., str], *args) -> Callable[..., str]:
+      # Body
+
+Note that there are no square brackets around the ellipsis.  The
+arguments of the callback are completely unconstrained in this case
+(and keyword arguments are acceptable).
+
+Since using callbacks with keyword arguments is not perceived as a
+common use case, there is currently no support for specifying keyword
+arguments with ``Callable``.  Similarly, there is no support for
+specifying callback signatures with a variable number of argument of a
+specific type.
 
 
 Generics
@@ -106,7 +161,7 @@
 
   from typing import Mapping, Set
 
-  def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]): ...
+  def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...
 
 Generics can be parametrized by using a new factory available in
 ``typing`` called ``TypeVar``.  Example::
@@ -149,13 +204,13 @@
 definition may be expressed as a string, to be resolved later.  For
 example, instead of writing::
 
-  def notify_by_email(employees: Set[Employee]): ...
+  def notify_by_email(employees: Set[Employee]) -> None: ...
 
 one might write::
 
-  def notify_by_email(employees: 'Set[Employee]'): ...
+  def notify_by_email(employees: 'Set[Employee]') -> None: ...
 
-.. FIXME: Rigorously define this.  Defend it, or find an alternative.
+.. FIXME: Rigorously define this, and give a motivational example.
 
 
 Union types
@@ -167,7 +222,7 @@
 
   from typing import Union
 
-  def handle_employees(e: Union[Employee, Sequence[Employee]]):
+  def handle_employees(e: Union[Employee, Sequence[Employee]]) -> None:
       if isinstance(e, Employee):
           e = [e]
       ...
@@ -180,14 +235,14 @@
 ``None`` is an invalid value for any type, unless a default value of
 ``None`` has been provided in the function definition.  Examples::
 
-  def handle_employee(e: Union[Employee, None]): ...
+  def handle_employee(e: Union[Employee, None]) -> None: ...
 
 As a shorthand for ``Union[T1, None]`` you can write ``Optional[T1]``;
 for example, the above is equivalent to::
 
   from typing import Optional
 
-  def handle_employee(e: Optional[Employee]): ...
+  def handle_employee(e: Optional[Employee]) -> None: ...
 
 An optional type is also automatically assumed when the default value is
 ``None``, for example::
@@ -196,14 +251,21 @@
 
 This is equivalent to::
 
-  def handle_employee(e: Optional[Employee] = None): ...
+  def handle_employee(e: Optional[Employee] = None) -> None: ...
 
-.. FIXME: Is this really a good idea?
+The ``Any`` type
+----------------
 
-A special kind of union type is ``Any``, a class that responds
-``True`` to ``issubclass`` of any class.  This lets the user
-explicitly state that there are no constraints on the type of a
-specific argument or return value.
+A special kind of type is ``Any``.  Every class is a subclass of
+``Any``.  This is also true for the builtin class ``object``.
+However, to the static type checker these are completely different.
+
+When the type of a value is ``object``, the type checker will reject
+almost all operations on it, and assigning it to a variable (or using
+it as a return value) of a more specialized type is a type error.  On
+the other hand, when a value has type ``Any``, the type checker will
+allow all operations on it, and a value of type `Any`` can be assigned
+to a variable (or used as a return value) of a more constrained type.
 
 
 Platform-specific type checking
@@ -227,6 +289,8 @@
   else:
       loop = UnixSelectorEventLoop
 
+.. FIXME: Also define PY3 and POSIX?
+
 Arbitrary literals defined in the form of ``NAME = True`` will also be
 accepted by the type checker to differentiate type resolution::
 
@@ -250,7 +314,7 @@
 A number of existing or potential use cases for function annotations
 exist, which are incompatible with type hinting.  These may confuse a
 static type checker.  However, since type hinting annotations have no
-run time behavior (other than evaluation of the annotation expression
+runtime behavior (other than evaluation of the annotation expression
 and storing annotations in the ``__annotations__`` attribute of the
 function object), this does not make the program incorrect -- it just
 makes it issue warnings when a static analyzer is used.
@@ -258,12 +322,16 @@
 To mark portions of the program that should not be covered by type
 hinting, use the following:
 
-* a ``@no_type_checks`` decorator on classes and functions
+* a ``@no_type_check`` decorator on classes and functions
 
 * a ``# type: ignore`` comment on arbitrary lines
 
 .. FIXME: should we have a module-wide comment as well?
 
+.. FIXME: suggest that other uses of annotations be replaced with decorators
+
+.. FIXME: add reference to "rejected alternatives"
+
 
 Type Hints on Local and Global Variables
 ========================================
@@ -275,7 +343,7 @@
   x = []   # type: List[Employee]
 
 In the case where type information for a local variable is needed before
-if was declared, an ``Undefined`` placeholder might be used::
+it is declared, an ``Undefined`` placeholder might be used::
 
   from typing import Undefined
 
@@ -285,17 +353,142 @@
 If type hinting proves useful in general, a syntax for typing variables
 may be provided in a future Python version.
 
+Casts
+=====
 
-Explicit raised exceptions
-==========================
+Occasionally the type checker may need a different kind of hint: the
+programmer may know that an expression is of a more constrained type
+than the type checker infers.  For example::
 
-No support for listing explicitly raised exceptions is being defined by
-this PEP.  Currently the only known use case for this feature is
-documentational, in which case the recommendation is to put this
-information in a docstring.
+  from typing import List
 
+  def find_first_str(a: List[object]) -> str:
+      index = next(i for i, x in enumerate(a) if isinstance(x, str))
+      # We only get here if there's at least one string in a
+      return cast(str, a[index])
 
-The ``typing`` package
+The type checker infers the type ``object`` for ``a[index]``, but we
+know that (if the code gets to that point) it must be a string.  The
+``cast(t, x)`` call tells the type checker that we are confident that
+the type of ``x`` is ``t``.  At runtime a cast always returns the
+expression unchanged -- it does not check the type, and it does not
+convert or coerce the value.
+
+Casts differ from type comments (see the previous section).  When
+using a type comment, the type checker should still verify that the
+inferred type is consistent with the stated type.  When using a cast,
+the type checker trusts the programmer.  Also, casts can be used in
+expressions, while type comments only apply to assignments.
+
+
+Stub Files
+==========
+
+Stub files are files containing type hints that are only for use by
+the type checker, not at runtime.  There are several use cases for
+stub files:
+
+* Extension modules
+
+* 3rd party modules whose authors have not yet added type hints
+
+* Standard library modules for which type hints have not yet been written
+
+* Modules that must be compatible with Python 2 and 3
+
+* Modules that use annotations for other purposes
+
+Stub files have the same syntax as regular Python modules.  There is
+one feature of the ``typing`` module that may only be used in stub
+files: the ``@overload`` decorator described below.
+
+The type checker should only check function signatures in stub files;
+function bodies in stub files should just be a single ``pass`` statement.
+
+The type checker should have a configurable search path for stub
+files.  If a stub file is found the type checker should not read the
+corresponding "real" module.
+
+Stub files may use the ``.py`` extension or alternatively may use the
+``.pyi`` extension.  The latter makes it possible to maintain stub
+files in the same directory as the corresponding real module.
+
+Function overloading
+--------------------
+
+The ``@overload`` decorator allows describing functions that support
+multiple different combinations of argument types.  This pattern is
+used frequently in builtin modules and types.  For example, the
+``__getitem__()`` method of the ``bytes`` type can be described as
+follows::
+
+  from typing import overload
+
+  class bytes:
+    ...
+    @overload
+    def __getitem__(self, i: int) -> int: pass
+    @overload
+    def __getitem__(self, s: slice) -> bytes: pass
+
+This description is more precise than would be possible using unions
+(which cannot express the relationship between the argument and return
+types)::
+
+  from typing import Union
+  class bytes:
+    ...
+    def __getitem__(self, a: Union[int, slice]) -> Union[int, bytes]: pass
+
+Another example where ``@overload`` comes in handy is the type of the
+builtin ``map()`` function, which takes a different number of
+arguments depending on the type of the callable::
+
+  from typing import Callable, Iterable, Iterator, Tuple, TypeVar, overload
+
+  T1 = TypeVar('T1')
+  T2 = TypeVar('T2)
+  S = TypeVar('S')
+
+  @overload
+  def map(func: Callable[[T1], S], iter1: Iterable[T1]) -> Iterator[S]: pass
+  @overload
+  def map(func: Callable[[T1, T2], S],
+          iter1: Iterable[T1], iter2: Iterable[T2]) -> Iterator[S]: pass
+  # ... and we could add more items to support more than two iterables
+
+Note that we could also easily add items to support ``map(None, ...)``::
+
+  @overload
+  def map(func: None, iter1: Iterable[T1]) -> Iterable[T1]: pass
+  @overload
+  def map(func: None,
+          iter1: Iterable[T1],
+          iter2: Iterable[T2]) -> Iterable[Tuple[T1, T2]]: pass
+
+The ``@overload`` decorator may only be used in stub files.  While it
+would be possible to provide a multiple dispatch implementation using
+this syntax, its implementation would require using
+``sys._getframe()``, which is frowned upon.  Also, designing and
+implementing an efficient multiple dispatch mechanism is hard, which
+is why previous attempts were abandoned in favor of
+``functools.singledispatch()``.  (See PEP 443, especially its section
+"Alternative approaches".)  In the future we may come up with a
+satisfactory multiple dispatch design, but we don't want such a design
+to be constrained by the overloading syntax defined for type hints in
+stub files.
+
+
+Exceptions
+==========
+
+No syntax for listing explicitly raised exceptions is proposed.
+Currently the only known use case for this feature is documentational,
+in which case the recommendation is to put this information in a
+docstring.
+
+
+The ``typing`` Package
 ======================
 
 To open the usage of static type checking to Python 3.5 as well as older
@@ -312,10 +505,17 @@
 
 * FrozenSet, used as ``FrozenSet[element_type]``
 
-* Tuple, used as ``Tuple[index0_type, index1_type, ...]``.
-  Arbitrary-length tuples might be expressed using ellipsis, in which
-  case the following arguments are considered the same type as the last
-  defined type on the tuple.
+* Tuple, used by listing the element types, for example
+  ``Tuple[int, int, str]``.
+  Arbitrary-length homogeneous tuples can be expressed
+  using one type and ellipsis, for example ``Tuple[int, ...]``.
+  (The ``...`` here are part of the syntax.)
+
+The generic versions of concrete collection types (``Dict``, ``List``,
+``Set``, ``FrozenSet``, and homogeneous arbitrary-length ``Tuple``)
+are mainly useful for annotating return values.  For arguments, prefer
+the abstract collection types defined below, e.g.  ``Mapping``,
+``Sequence`` or ``AbstractSet``.
 
 It also introduces factories and helper members needed to express
 generics and union types:
@@ -333,8 +533,6 @@
 
 * Callable, used as ``Callable[[Arg1Type, Arg2Type], ReturnType]``
 
-* AnyArgs, used as ``Callable[AnyArgs, ReturnType]``
-
 * AnyStr, equivalent to ``TypeVar('AnyStr', str, bytes)``
 
 All abstract base classes available in ``collections.abc`` are
@@ -385,7 +583,7 @@
 
 * WINDOWS
 
-* UNIXOID, equivalent to ``not WINDOWS``
+* POSIX, equivalent to ``not WINDOWS``
 
 The following types are available in the ``typing.io`` module:
 
@@ -408,7 +606,7 @@
 The place of the ``typing`` module in the standard library
 ----------------------------------------------------------
 
-.. FIXME: complete this section
+.. FIXME: complete this section (or discard?)
 
 
 Usage Patterns
@@ -417,8 +615,8 @@
 The main use case of type hinting is static analysis using an external
 tool without executing the analyzed program.  Existing tools used for
 that purpose like ``pyflakes`` [pyflakes]_ or ``pylint`` [pylint]_
-might be extended to support type checking.  New tools, like mypy's
-``mypy -S`` mode, can be adopted specifically for this purpose.
+might be extended to support type checking.  New tools, like mypy [mypy]_,
+can be adopted specifically for this purpose.
 
 Type checking based on type hints is understood as a best-effort
 mechanism.  In other words, whenever types are not annotated and cannot
@@ -431,20 +629,246 @@
 The implementation of a type checker, whether linting source files or
 enforcing type information during runtime, is out of scope for this PEP.
 
-.. FIXME: Describe stub modules.
+.. FIXME: This is somewhat redundant with the updated initial sections.
 
 .. FIXME: Describe run-time behavior of generic types.
 
 
-Existing Approaches
-===================
+Rejected Alternatives
+=====================
 
-PEP 482 lists existing approaches in Python and other languages.
+During discussion of earlier drafts of this PEP, various objections
+were raised and alternatives were proposed.  We discuss some of these
+here and explain why we reject them.
 
+Several main objections were raised.
 
-Is type hinting Pythonic?
+Which brackets for generic type parameters?
+-------------------------------------------
+
+Most people are familiar with the use of angular brackets
+(e.g. ``List<int>``) in languages like C++, Java, C# and Swift to
+express the parametrization of generic types.  The problem with these
+is that they are really hard to parse, especially for a simple-minded
+parser like Python.  In most languages the ambiguities are usually
+dealy with by only allowing angular brackets in specific syntactic
+positions, where general expressions aren't allowed.  (And also by
+using very powerful parsing techniques that can backtrack over an
+arbitrary section of code.)
+
+But in Python, we'd like type expressions to be (syntactically) the
+same as other expressions, so that we can use e.g. variable assignment
+to create type aliases.  Consider this simple type expression::
+
+    List<int>
+
+From the Python parser's perspective, the expression begins with the
+same four tokens (NAME, LESS, NAME, GREATER) as a chained comparison::
+
+    a < b > c  # I.e., (a < b) and (b > c)
+
+We can even make up an example that could be parsed both ways::
+
+    a < b > [ c ]
+
+Assuming we had angular brackets in the language, this could be
+interpreted as either of the following two::
+
+    (a<b>)[c]      # I.e., (a<b>).__getitem__(c)
+    a < b > ([c])  # I.e., (a < b) and (b > [c])
+
+It would surely be possible to come up with a rule to disambiguate
+such cases, but to most users the rules would feel arbitrary and
+complex.  It would also require us to dramatically change the CPython
+parser (and every other parser for Python).  It should be noted that
+Python's current parser is intentionally "dumb" -- a simple grammar is
+easier for users to reason about.
+
+For all these reasons, square brackets (e.g. ``List[int]``) are (and
+have long been) the preferred syntax for generic type parameters.
+They can be implemented by defining the ``__getitem__()`` method on
+the metaclass, and no new syntax is required at all.  This option
+works in all recent versions of Python (starting with Python 2.2).
+Python is not alone in this syntactic choice -- generic classes in
+Scala also use square brackets.
+
+What about existing uses of annotations?
+----------------------------------------
+
+One line of argument points out that PEP 3107 explicitly supports
+the use of arbitrary expressions in function annotations.  The new
+proposal is then considered incompatible with the specification of PEP
+3107.
+
+Our response to this is that, first of all, the current proposal does
+not introduce any direct incompatibilities, so programs using
+annotations in Python 3.4 will still work correctly and without
+prejudice in Python 3.5.
+
+We do hope that type hints will eventually become the sole use for
+annotations, but this will require additional discussion and a
+deprecation period after the initial roll-out of the typing module
+with Python 3.5.  The current PEP will have provisional status (see
+PEP 411) until Python 3.6 is released.  The fastest conceivable scheme
+would introduce silent deprecation of non-type-hint annotations in
+3.6, full deprecation in 3.7, and declare type hints as the only
+allowed use of annotations in Python 3.8.  This should give authors of
+packages that use annotations plenty of time to devise another
+approach, even if type hints become an overnight success.
+
+Another possible outcome would be that type hints will eventually
+become the default meaning for annotations, but that there will always
+remain an option to disable them.  For this purpose the current
+proposal defines a decorator ``@no_type_check`` which disables the
+default interpretation of annotations as type hints in a given class
+or function.  It also defines a meta-decorator
+``@no_type_check_decorator`` which can be used to decorate a decorator
+(!), causing annotations in any function or class decorated with the
+latter to be ignored by the type checker.
+
+There are also ``# type: ignore`` comments, and static checkers should
+support configuration options to disable type checking in selected
+packages.
+
+Despite all these options, proposals have been circulated to allow
+type hints and other forms of annotations to coexist for individual
+arguments.  One proposal suggests that if an annotation for a given
+argument is a dictionary literal, each key represents a different form
+of annotation, and the key ``'type'`` would be use for type hints.
+The problem with this idea and its variants is that the notation
+becomes very "noisy" and hard to read.  Also, in most cases where
+existing libraries use annotations, there would be little need to
+combine them with type hints.  So the simpler approach of selectively
+disabling type hints appears sufficient.
+
+The problem of forward declarations
+-----------------------------------
+
+The current proposal is admittedly sub-optimal when type hints must
+contain forward references.  Python requires all names to be defined
+by the time they are used.  Apart from circular imports this is rarely
+a problem: "use" here means "look up at runtime", and with most
+"forward" references there is no problem in ensuring that a name is
+defined before the function using it is called.
+
+The problem with type hints is that annotations (per PEP 3107, and
+similar to default values) are evaluated at the time a function is
+defined, and thus any names used in an annotation must be already
+defined when the function is being defined.  A common scenario is a
+class definition whose methods need to reference the class itself in
+their annotations.  (More general, it can also occur with mutually
+recursive classes.)  This is natural for container types, for
+example::
+
+  class Node:
+      """Binary tree node."""
+
+      def __init__(self, left: Node, right: None):
+          self.left = left
+          self.right = right
+
+As written this will not work, because of the peculiarity in Python
+that class names become defined once the entire body of the class has
+been executed.  Our solution, which isn't particularly elegant, but
+gets the job done, is to allow using string literals in annotations.
+Most of the time you won't have to use this though -- most _uses_ of
+type hints are expected to reference builtin types or types defined in
+other modules.
+
+A counterproposal would change the semantics of type hints so they
+aren't evaluated at runtime at all (after all, type checking happens
+off-line, so why would type hints need to be evaluated at runtime at
+all).  This of course would run afoul of backwards compatibility,
+since the Python interpreter doesn't actually know whether a
+particular annotation is meant to be a type hint or something else.
+
+The double colon
+----------------
+
+A few creative souls have tried to invent solutions for this problem.
+For example, it was proposed to use a double colon (``::``) for type
+hints, solving two problems at once: disambiguating between type hints
+and other annotations, and changing the semantics to preclude runtime
+evaluation.  There are several things wrong with this idea, however.
+
+* It's ugly.  The single colon in Python has many uses, and all of
+  them look familiar because they resemble the use of the colon in
+  English text.  This is a general rule of thumb by which Python
+  abides for most forms of punctuation; the exceptions are typically
+  well known from other programming languages.  But this use of ``::``
+  is unheard of in English, and in other languages (e.g. C++) it is
+  used as a scoping operator, which is a very different beast.  In
+  contrast, the single colon for type hints reads natural -- and no
+  wonder, since it was carefully designed for this purpose (the idea
+  long predates PEP 3107 [gvr-artima]_).  It is also used in the same
+  fashion in other languages from Pascal to Swift.
+
+* What would you do for return type annotations?
+
+* It's actually a feature that type hints are evaluated at runtime.
+
+  * Making type hints available at runtime allows runtime type
+    checkers to be built on top of type hints.
+
+  * It catches mistakes even when the type checker is not run.  Since
+    it is a separate program, users may choose not to run it (or even
+    install it), but might still want to use type hints as a concise
+    form of documentation.  Broken type hints are no use even for
+    documentation.
+
+* Because it's new syntax, using the double colon for type hints would
+  limit them to code that works with Python 3.5 only.  By using
+  existing syntax, the current proposal can easily work for older
+  versions of Python 3.  (And in fact mypy supports Python 3.2 and
+  newer.)
+
+* If type hints become successful we may well decide to add new syntax
+  in the future to declare the type for variables, for example
+  ``var age: int = 42``.  If we were to use a double colon for
+  argument type hints, for consistency we'd have to use the same
+  convention for future syntax, perpetuating the ugliness.
+
+Other forms of new syntax
+-------------------------
+
+A few other forms of alternative syntax have been proposed, e.g. the
+introduction of a ``where`` keyword [roberge]_, and Cobra-inspired
+``requires`` clauses.  But these all share a problem with the double
+colon: they won't work for earlier versions of Python 3.  The same
+would apply to a new ``__future__`` import.
+
+Other backwards compatible conventions
+--------------------------------------
+
+The ideas put forward include:
+
+* A decorator, e.g. ``@typehints(name=str, returns=str)``.  This could
+  work, but it's pretty verbose (an extra line, and the argument names
+  must be repeated), and a far cry in elegance from the PEP 3107
+  notation.
+
+* Stub files.  We do want stub files, but they are primarily useful
+  for adding type hints to existing code that doesn't lend itself to
+  adding type hints, e.g. 3rd party packages, code that needs to
+  support both Python 2 and Python 3, and especially extension
+  modules.  For most situations, having the annotations in line with
+  the function definitions makes them much more useful.
+
+* Docstrings.  There is an existing convention for docstrings, based
+  on the Sphinx notation (``:type arg1: description``).  This is
+  pretty verbose (an extra line per parameter), and not very elegant.
+  We could also make up something new, but the annotation syntax is
+  hard to beat (because it was designed for this very purpose).
+
+It's also been proposed to simply wait another release.  But what
+problem would that solve?  It would just be procrastination.
+
+
+Is Type Hinting Pythonic?
 =========================
 
+.. FIXME: Do we really need this section?
+
 Type annotations provide important documentation for how a unit of code
 should be used.  Programmers should therefore provide type hints on
 public APIs, namely argument and return types on functions and methods
@@ -460,6 +884,18 @@
 indeed *Pythonic*.
 
 
+PEP Development Process
+=======================
+
+A live draft for this PEP lives on GitHub [github]_.  There is also an
+issue tracker [issues]_, where much of the technical discussion takes
+place.
+
+The draft on GitHub is updated regularly in small increments.  The
+official PEPS repo [peps_] is (usually) only updated when a new draft
+is posted to python-dev.
+
+
 Acknowledgements
 ================
 
@@ -486,6 +922,21 @@
 .. [pylint]
    http://www.pylint.org
 
+.. [gvr-artima]
+   http://www.artima.com/weblogs/viewpost.jsp?thread=85551
+
+.. [roberge]
+   http://aroberge.blogspot.com/2015/01/type-hinting-in-python-focus-on.html
+
+.. [github]
+   https://github.com/ambv/typehinting
+
+.. [issues]
+   https://github.com/ambv/typehinting/issues
+
+.. [peps]
+   https://hg.python.org/peps/file/tip/pep-0484.txt
+
 
 Copyright
 =========

-- 
Repository URL: https://hg.python.org/peps


More information about the Python-checkins mailing list