<div dir="ltr"><div><div>Another draft. This is mostly a bunch of clarifications and minor edits, but it also removes the four version/platform constants (PY2, PY3, WINDOWS, POSIX) in favor of asking type checkers to recognize common version checks e.g. using sys.version_info or sys.platform. This time I think the new version *will* appear on <a href="http://python.org">python.org</a>. For more frequent updates, watch <a href="https://github.com/ambv/typehinting">https://github.com/ambv/typehinting</a> .<br><br></div>Also note: I'm probably going to commit the typing.py module to the CPython repo optimistically, while Mark is still pondering his decision. Off-list he's told me he's happy with the PEP. I have to make some changes to typing.py to satisfy him; I won't have time to work on those this afternoon, and I don't want to miss (or hold up) Larry's tagging of the tree for beta 1. So a few things may end up as bugs in the issue tracker (<a href="https://github.com/ambv/typehinting/issues">https://github.com/ambv/typehinting/issues</a>) and I'll rectify those before beta 2.<br></div><div><br></div>--Guido<br><div><div><div><div class="gmail_extra"><br>PEP: 484<br>Title: Type Hints<br>Version: $Revision$<br>Last-Modified: $Date$<br>Author: Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>>, Jukka Lehtosalo <<a href="mailto:jukka.lehtosalo@iki.fi">jukka.lehtosalo@iki.fi</a>>, Łukasz Langa <<a href="mailto:lukasz@langa.pl">lukasz@langa.pl</a>><br>BDFL-Delegate: Mark Shannon<br>Discussions-To: Python-Dev <<a href="mailto:python-dev@python.org">python-dev@python.org</a>><br>Status: Draft<br>Type: Standards Track<br>Content-Type: text/x-rst<br>Created: 29-Sep-2014<br>Post-History: 16-Jan-2015,20-Mar-2015,17-Apr-2015,20-May-2015,22-May-2015<br>Resolution:<br><br><br>Abstract<br>========<br><br>PEP 3107 introduced syntax for function annotations, but the semantics<br>were deliberately left undefined.  There has now been enough 3rd party<br>usage for static type analysis that the community would benefit from<br>a standard vocabulary and baseline tools within the standard library.<br><br>This PEP introduces a provisional module to provide these standard<br>definitions and tools, along with some conventions for situations<br>where annotations are not available.<br><br>Note that this PEP still explicitly does NOT prevent other uses of<br>annotations, nor does it require (or forbid) any particular processing<br>of annotations, even when they conform to this specification.  It<br>simply enables better coordination, as PEP 333 did for web frameworks.<br><br>For example, here is a simple function whose argument and return type<br>are declared in the annotations::<br><br>  def greeting(name: str) -> str:<br>      return 'Hello ' + name<br><br>While these annotations are available at runtime through the usual<br>``__annotations__`` attribute, *no type checking happens at runtime*.<br>Instead, the proposal assumes the existence of a separate off-line<br>type checker which users can run over their source code voluntarily.<br>Essentially, such a type checker acts as a very powerful linter.<br>(While it would of course be possible for individual users to employ<br>a similar checker at run time for Design By Contract enforcement or<br>JIT optimization, those tools are not yet as mature.)<br><br>The proposal is strongly inspired by mypy [mypy]_.  For example, the<br>type "sequence of integers" can be written as ``Sequence[int]``.  The<br>square brackets mean that no new syntax needs to be added to the<br>language.  The example here uses a custom type ``Sequence``, imported<br>from a pure-Python module ``typing``.  The ``Sequence[int]`` notation<br>works at runtime by implementing ``__getitem__()`` in the metaclass<br>(but its significance is primarily to an offline type checker).<br><br>The type system supports unions, generic types, and a special type<br>named ``Any`` which is consistent with (i.e. assignable to and from) all<br>types.  This latter feature is taken from the idea of gradual typing.<br>Gradual typing and the full type system are explained in PEP 483.<br><br>Other approaches from which we have borrowed or to which ours can be<br>compared and contrasted are described in PEP 482.<br><br><br>Rationale and Goals<br>===================<br><br>PEP 3107 added support for arbitrary annotations on parts of a<br>function definition.  Although no meaning was assigned to annotations<br>then, there has always been an implicit goal to use them for type<br>hinting [gvr-artima]_, which is listed as the first possible use case<br>in said PEP.<br><br>This PEP aims to provide a standard syntax for type annotations,<br>opening up Python code to easier static analysis and refactoring,<br>potential runtime type checking, and (perhaps, in some contexts)<br>code generation utilizing type information.<br><br>Of these goals, static analysis is the most important.  This includes<br>support for off-line type checkers such as mypy, as well as providing<br>a standard notation that can be used by IDEs for code completion and<br>refactoring.<br><br>Non-goals<br>---------<br><br>While the proposed typing module will contain some building blocks for<br>runtime type checking -- in particular a useful ``isinstance()``<br>implementation -- third party packages would have to be developed to<br>implement specific runtime type checking functionality, for example<br>using decorators or metaclasses.  Using type hints for performance<br>optimizations is left as an exercise for the reader.<br><br>It should also be emphasized that **Python will remain a dynamically<br>typed language, and the authors have no desire to ever make type hints<br>mandatory, even by convention.**<br><br><br>The meaning of annotations<br>==========================<br><br>Any function without annotations should be treated as having the most<br>general type possible, or ignored, by any type checker.  Functions<br>with the ``@no_type_check`` decorator or with a ``# type: ignore``<br>comment should be treated as having no annotations.<br><br>It is recommended but not required that checked functions have<br>annotations for all arguments and the return type.  For a checked<br>function, the default annotation for arguments and for the return type<br>is ``Any``.  An exception is that the first argument of instance and<br>class methods does not need to be annotated; it is assumed to have the<br>type of the containing class for instance methods, and a type object<br>type corresponding to the containing class object for class methods.<br>For example, in class ``A`` the first argument of an instance method<br>has the implicit type ``A``. In a class method, the precise type of<br>the first argument cannot be represented using the available type<br>notation.<br><br>(Note that the return type of ``__init__`` ought to be annotated with<br>``-> None``.  The reason for this is subtle.  If ``__init__`` assumed<br>a return annotation of ``-> None``, would that mean that an<br>argument-less, un-annotated ``__init__`` method should still be<br>type-checked?  Rather than leaving this ambiguous or introducing an<br>exception to the exception, we simply say that ``__init__`` ought to<br>have a return annotation; the default behavior is thus the same as for<br>other methods.)<br><br>A type checker is expected to check the body of a checked function for<br>consistency with the given annotations.  The annotations may also used<br>to check correctness of calls appearing in other checked functions.<br><br>Type checkers are expected to attempt to infer as much information as<br>necessary.  The minimum requirement is to handle the builtin<br>decorators ``@property``, ``@staticmethod`` and ``@classmethod``.<br><br><br>Type Definition Syntax<br>======================<br><br>The syntax leverages PEP 3107-style annotations with a number of<br>extensions described in sections below.  In its basic form, type<br>hinting is used by filling function annotation slots with classes::<br><br>  def greeting(name: str) -> str:<br>      return 'Hello ' + name<br><br>This states that the expected type of the ``name`` argument is<br>``str``.  Analogically, the expected return type is ``str``.<br><br>Expressions whose type is a subtype of a specific argument type are<br>also accepted for that argument.<br><br><br>Acceptable type hints<br>---------------------<br><br>Type hints may be built-in classes (including those defined in<br>standard library or third-party extension modules), abstract base<br>classes, types available in the ``types`` module, and user-defined<br>classes (including those defined in the standard library or<br>third-party modules).<br><br>While annotations are normally the best format for type hints,<br>there are times when it is more appropriate to represent them<br>by a special comment, or in a separately distributed stub<br>file.  (See below for examples.)<br><br>Annotations must be valid expressions that evaluate without raising<br>exceptions at the time the function is defined (but see below for<br>forward references).<br><br>Annotations should be kept simple or static analysis tools may not be<br>able to interpret the values. For example, dynamically computed types<br>are unlikely to be understood.  (This is an<br>intentionally somewhat vague requirement, specific inclusions and<br>exclusions may be added to future versions of this PEP as warranted by<br>the discussion.)<br><br>In addition to the above, the following special constructs defined<br>below may be used: ``None``, ``Any``, ``Union``, ``Tuple``,<br>``Callable``, all ABCs and stand-ins for concrete classes exported<br>from ``typing`` (e.g. ``Sequence`` and ``Dict``), type variables, and<br>type aliases.<br><br>All newly introduced names used to support features described in<br>following sections (such as ``Any`` and ``Union``) are available in<br>the ``typing`` module.<br><br><br>Using None<br>----------<br><br>When used in a type hint, the expression ``None`` is considered<br>equivalent to ``type(None)``.<br><br><br>Type aliases<br>------------<br><br>Type aliases are defined by simple variable assignments::<br><br>  Url = str<br><br>  def retry(url: Url, retry_count: int) -> None: ...<br><br>Note that we recommend capitalizing alias names, since they represent<br>user-defined types, which (like user-defined classes) are typically<br>spelled that way.<br><br>Type aliases may be as complex as type hints in annotations --<br>anything that is acceptable as a type hint is acceptable in a type<br>alias::<br><br>    from typing import TypeVar, Iterable, Tuple<br><br>    T = TypeVar('T', int, float, complex)<br>    Vector = Iterable[Tuple[T, T]]<br><br>    def inproduct(v: Vector) -> T:<br>        return sum(x*y for x, y in v)<br><br>This is equivalent to::<br><br>    from typing import TypeVar, Iterable, Tuple<br><br>    T = TypeVar('T', int, float, complex)<br><br>    def inproduct(v: Iterable[Tuple[T, T]]) -> T:<br>        return sum(x*y for x, y in v)<br><br><br>Callable<br>--------<br><br>Frameworks expecting callback functions of specific signatures might be<br>type hinted using ``Callable[[Arg1Type, Arg2Type], ReturnType]``.<br>Examples::<br><br>  from typing import Callable<br><br>  def feeder(get_next_item: Callable[[], str]) -> None:<br>      # Body<br><br>  def async_query(on_success: Callable[[int], None],<br>                  on_error: Callable[[int, Exception], None]) -> None:<br>      # Body<br><br>It is possible to declare the return type of a callable without<br>specifying the call signature by substituting a literal ellipsis<br>(three dots) for the list of arguments::<br><br>  def partial(func: Callable[..., str], *args) -> Callable[..., str]:<br>      # Body<br><br>Note that there are no square brackets around the ellipsis.  The<br>arguments of the callback are completely unconstrained in this case<br>(and keyword arguments are acceptable).<br><br>Since using callbacks with keyword arguments is not perceived as a<br>common use case, there is currently no support for specifying keyword<br>arguments with ``Callable``.  Similarly, there is no support for<br>specifying callback signatures with a variable number of argument of a<br>specific type.<br><br><br>Generics<br>--------<br><br>Since type information about objects kept in containers cannot be<br>statically inferred in a generic way, abstract base classes have been<br>extended to support subscription to denote expected types for container<br>elements.  Example::<br><br>  from typing import Mapping, Set<br><br>  def notify_by_email(employees: Set[Employee], overrides: Mapping[str, str]) -> None: ...<br><br>Generics can be parametrized by using a new factory available in<br>``typing`` called ``TypeVar``.  Example::<br><br>  from typing import Sequence, TypeVar<br><br>  T = TypeVar('T')      # Declare type variable<br><br>  def first(l: Sequence[T]) -> T:   # Generic function<br>      return l[0]<br><br>In this case the contract is that the returned value is consistent with<br>the elements held by the collection.<br><br>A ``TypeVar()`` expression must always directly be assigned to a<br>variable (it should not be used as part of a larger expression).  The<br>argument to ``TypeVar()`` must be a string equal to the variable name<br>to which it is assigned.  Type variables must not be redefined.<br><br>``TypeVar`` supports constraining parametric types to a fixed set of<br>possible types.  For example, we can define a type variable that ranges<br>over just ``str`` and ``bytes``.  By default, a type variable ranges<br>over all possible types.  Example of constraining a type variable::<br><br>  from typing import TypeVar<br><br>  AnyStr = TypeVar('AnyStr', str, bytes)<br><br>  def concat(x: AnyStr, y: AnyStr) -> AnyStr:<br>      return x + y<br><br>The function ``concat`` can be called with either two ``str`` arguments<br>or two ``bytes`` arguments, but not with a mix of ``str`` and ``bytes``<br>arguments.<br><br>There should be at least two constraints, if any; specifying a single<br>constraint is disallowed.<br><br>Subtypes of types constrained by a type variable should be treated<br>as their respective explicitly listed base types in the context of the<br>type variable.  Consider this example::<br><br>  class MyStr(str): ...<br><br>  x = concat(MyStr('apple'), MyStr('pie'))<br><br>The call is valid but the type variable ``AnyStr`` will be set to<br>``str`` and not ``MyStr``. In effect, the inferred type of the return<br>value assigned to ``x`` will also be ``str``.<br><br>Additionally, ``Any`` is a valid value for every type variable.<br>Consider the following::<br><br>  def count_truthy(elements: List[Any]) -> int:<br>      return sum(1 for elem in elements if element)<br><br>This is equivalent to omitting the generic notation and just saying<br>``elements: List``.<br><br><br>User-defined generic types<br>--------------------------<br><br>You can include a ``Generic`` base class to define a user-defined class<br>as generic.  Example::<br><br>  from typing import TypeVar, Generic<br><br>  T = TypeVar('T')<br><br>  class LoggedVar(Generic[T]):<br>      def __init__(self, value: T, name: str, logger: Logger) -> None:<br>          <a href="http://self.name">self.name</a> = name<br>          self.logger = logger<br>          self.value = value<br><br>      def set(self, new: T) -> None:<br>          self.log('Set ' + repr(self.value))<br>          self.value = new<br><br>      def get(self) -> T:<br>          self.log('Get ' + repr(self.value))<br>          return self.value<br><br>      def log(self, message: str) -> None:<br>          <a href="http://self.logger.info">self.logger.info</a>('{}: {}'.format(<a href="http://self.name">self.name</a> message))<br><br>``Generic[T]`` as a base class defines that the class ``LoggedVar``<br>takes a single type parameter ``T``. This also makes ``T`` valid as<br>a type within the class body.<br><br>The ``Generic`` base class uses a metaclass that defines ``__getitem__``<br>so that ``LoggedVar[t]`` is valid as a type::<br><br>  from typing import Iterable<br><br>  def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:<br>      for var in vars:<br>          var.set(0)<br><br>A generic type can have any number of type variables, and type variables<br>may be constrained. This is valid::<br><br>  from typing import TypeVar, Generic<br>  ...<br><br>  T = TypeVar('T')<br>  S = TypeVar('S')<br><br>  class Pair(Generic[T, S]):<br>      ...<br><br>Each type variable argument to ``Generic`` must be distinct. This is<br>thus invalid::<br><br>  from typing import TypeVar, Generic<br>  ...<br><br>  T = TypeVar('T')<br><br>  class Pair(Generic[T, T]):   # INVALID<br>      ...<br><br>You can use multiple inheritance with ``Generic``::<br><br>  from typing import TypeVar, Generic, Sized<br><br>  T = TypeVar('T')<br><br>  class LinkedList(Sized, Generic[T]):<br>      ...<br><br>Subclassing a generic class without specifying type parameters assumes<br>``Any`` for each position.  In the following example, ``MyIterable``<br>is not generic but implicitly inherits from ``Iterable[Any]``:<br><br>  from typing import Iterable<br><br>  class MyIterable(Iterable):  # Same as Iterable[Any]<br>      ...<br><br>Generic metaclasses are not supported.<br><br><br>Instantiating generic classes and type erasure<br>----------------------------------------------<br><br>Generic types like ``List`` or ``Sequence`` cannot be instantiated.<br>However, user-defined classes derived from them can be instantiated.<br>Suppose we write a ``Node`` class inheriting from ``Generic[T]``::<br><br>  from typing import TypeVar, Generic<br><br>  T = TypeVar('T')<br><br>  class Node(Generic[T]):<br>      ...<br><br>Now there are two ways we can instantiate this class; the type<br>inferred by a type checker may be different depending on the form we<br>use.  The first way is to give the value of the type parameter<br>explicitly -- this overrides whatever type inference the type<br>checker would otherwise perform:<br><br>  x = Node[T]()  # The type inferred for x is Node[T].<br><br>  y = Node[int]()  # The type inferred for y is Node[int].<br><br>If no explicit types are given, the type checker is given some<br>freedom. Consider this code:<br><br>  x = Node()<br><br>The inferred type could be ``Node[Any]``, as there isn't enough<br>context to infer a more precise type.  Alternatively, a type checker<br>may reject the line and require an explicit annotation, like this:<br><br>  x = Node()  # type: Node[int]  # Inferred type is Node[int].<br><br>A type checker with more powerful type inference could look at how<br>``x`` is used elsewhere in the file and try to infer a more precise<br>type such as ``Node[int]`` even without an explicit type annotation.<br>However, it is probably impossible to make such type inference work<br>well in all cases, since Python programs can be very dynamic.<br><br>This PEP doesn't specify the details of how type inference should<br>work.  We allow different tools to experiment with various approaches.<br>We may give more explicit rules in future revisions.<br><br>At runtime the type is not preserved, and the class of ``x`` is just<br>``Node`` in all cases.  This behavior is called "type erasure"; it is<br>common practice in languages with generics (e.g. Java, TypeScript).<br><br><br>Arbitrary generic types as base classes<br>---------------------------------------<br><br>``Generic[T]`` is only valid as a base class -- it's not a proper type.<br>However, user-defined generic types such as ``LinkedList[T]`` from the<br>above example and built-in generic types and ABCs such as ``List[T]``<br>and ``Iterable[T]`` are valid both as types and as base classes. For<br>example, we can define a subclass of ``Dict`` that specializes type<br>arguments::<br><br>  from typing import Dict, List, Optional<br><br>  class Node:<br>      ...<br><br>  class SymbolTable(Dict[str, List[Node]]):<br>      def push(self, name: str, node: Node) -> None:<br>          self.setdefault(name, []).append(node)<br><br>      def pop(self, name: str) -> Node:<br>          return self[name].pop()<br><br>      def lookup(self, name: str) -> Optional[Node]:<br>          nodes = self.get(name)<br>          if nodes:<br>              return nodes[-1]<br>          return None<br><br>``SymbolTable`` is a subclass of ``dict`` and a subtype of ``Dict[str,<br>List[Node]]``.<br><br>If a generic base class has a type variable as a type argument, this<br>makes the defined class generic. For example, we can define a generic<br>``LinkedList`` class that is iterable and a container::<br><br>  from typing import TypeVar, Iterable, Container<br><br>  T = TypeVar('T')<br><br>  class LinkedList(Iterable[T], Container[T]):<br>      ...<br><br>Now ``LinkedList[int]`` is a valid type. Note that we can use ``T``<br>multiple times in the base class list, as long as we don't use the<br>same type variable ``T`` multiple times within ``Generic[...]``.<br><br>Also consider the following example::<br><br>  from typing import TypeVar, Mapping<br><br>  T = TypeVar('T')<br><br>  class MyDict(Mapping[str, T]):<br>      ...<br><br>In this case MyDict has a single parameter, T.<br><br><br>Abstract generic types<br>----------------------<br><br>The metaclass used by ``Generic`` is a subclass of ``abc.ABCMeta``.<br>A generic class can be an ABC by including abstract methods<br>or properties, and generic classes can also have ABCs as base<br>classes without a metaclass conflict.<br><br><br>Type variables with an upper bound<br>----------------------------------<br><br>A type variable may specify an upper bound using ``bound=<type>``.<br>This means that an actual type substituted (explicitly or implictly)<br>for the type variable must be a subclass of the boundary type.  A<br>common example is the definition of a Comparable type that works well<br>enough to catch the most common errors::<br><br>  from typing import TypeVar<br><br>  class Comparable(metaclass=ABCMeta):<br>      @abstractmethod<br>      def __lt__(self, other: Any) -> bool: ...<br>      ... # __gt__ etc. as well<br><br>  CT = TypeVar('CT', bound=Comparable)<br><br>  def min(x: CT, y: CT) -> CT:<br>      if x < y:<br>          return x<br>      else:<br>          return y<br><br>  min(1, 2) # ok, return type int<br>  min('x', 'y') # ok, return type str<br><br>(Note that this is not ideal -- for example ``min('x', 1)`` is invalid<br>at runtime but a type checker would simply infer the return type<br>``Comparable``.  Unfortunately, addressing this would require<br>introducing a much more powerful and also much more complicated<br>concept, F-bounded polymorphism.  We may revisit this in the future.)<br><br>An upper bound cannot be combined with type constraints (as in used<br>``AnyStr``, see the example earlier); type constraints cause the<br>inferred type to be _exactly_ one of the constraint types, while an<br>upper bound just requires that the actual type is a subclass of the<br>boundary type.<br><br><br>Covariance and contravariance<br>-----------------------------<br><br>Consider a class ``Employee`` with a subclass ``Manager``.  Now<br>suppose we have a function with an argument annotated with<br>``List[Employee]``.  Should we be allowed to call this function with a<br>variable of type ``List[Manager]`` as its argument?  Many people would<br>answer "yes, of course" without even considering the consequences.<br>But unless we know more about the function, a type checker should<br>reject such a call: the function might append an ``Employee`` instance<br>to the list, which would violate the variable's type in the caller.<br><br>It turns out such an argument acts _contravariantly_, whereas the<br>intuitive answer (which is correct in case the function doesn't mutate<br>its argument!) requires the argument to act _covariantly_.  A longer<br>introduction to these concepts can be found on Wikipedia<br>[wiki-variance]_; here we just show how to control a type checker's<br>behavior.<br><br>By default type variables are considered _invariant_, which means that<br>arguments for arguments annotated with types like ``List[Employee]``<br>must exactly match the type annotation -- no subclasses or<br>superclasses of the type parameter (in this example ``Employee``) are<br>allowed.<br><br>To facilitate the declaration of container types where covariant type<br>checking is acceptable, a type variable can be declared using<br>``covariant=True``.  For the (rare) case where contravariant behavior<br>is desirable, pass ``contravariant=True``.  At most one of these may<br>be passed.<br><br>A typical example involves defining an immutable (or read-only)<br>container class::<br><br>  from typing import TypeVar, Generic, Iterable, Iterator<br><br>  T = TypeVar('T', covariant=True)<br><br>  class ImmutableList(Generic[T]):<br>      def __init__(self, items: Iterable[T]) -> None: ...<br>      def __iter__(self) -> Iterator[T]: ...<br>      ...<br><br>  class Employee: ...<br><br>  class Manager(Employee): ...<br><br>  def dump_employees(emps: ImmutableList[Employee]) -> None:<br>      for emp in emps:<br>          ...<br><br>  mgrs = ImmutableList([Manager()])  # type: ImmutableList[Manager]<br>  dump_employees(mgrs)  # OK<br><br>The read-only collection classes in ``typing`` are all defined using a<br>covariant type variable (e.g. ``Mapping`` and ``Sequence``).  The<br>mutable collection classes (e.g. ``MutableMapping`` and<br>``MutableSequence``) are defined using regular invariant type<br>variables.  The one example of a contravariant type variable is the<br>``Generator`` type, which is contravariant in the ``send()`` argument<br>type (see below).<br><br>Note: variance affects type parameters for generic types -- it does<br>not affect regular parameters.  For example, the following example is<br>fine::<br><br>  from typing import TypeVar<br><br>  class Employee: ...<br><br>  class Manager(Employee): ...<br><br>  E = TypeVar('E', bound=Employee)  # Invariant<br><br>  def dump_employee(e: E) -> None: ...<br><br>  dump_employee(Manager())  # OK<br><br><br>The numeric tower<br>-----------------<br><br>PEP 3141 defines Python's numeric tower, and the stdlib module<br>``numbers`` implements the corresponding ABCs (``Number``,<br>``Complex``, ``Real``, ``Rational`` and ``Integral``).  There are some<br>issues with these ABCs, but the built-in concrete numeric classes<br>``complex``, ``float`` and ``int`` are ubiquitous (especially the<br>latter two :-).<br><br>Rather than requiring that users write ``import numbers`` and then use<br>``numbers.Float`` etc., this PEP proposes a straightforward shortcut<br>that is almost as effective: when an argument is annotated as having<br>type ``float``, an argument of type ``int`` is acceptable; similar,<br>for an argument annotated as having type ``complex``, arguments of<br>type ``float`` or ``int`` are acceptable.  This does not handle<br>classes implementing the corresponding ABCs or the<br>``fractions.Fraction`` class, but we believe those use cases are<br>exceedingly rare.<br><br><br>The bytes types<br>---------------<br><br>There are three different builtin classes used for arrays of bytes<br>(not counting the classes available in the ``array`` module):<br>``bytes``, ``bytearray`` and ``memoryview``.  Of these, ``bytes`` and<br>``bytearray`` have many behaviors in common (though not all --<br>``bytearray`` is mutable).<br><br>While there is an ABC ``ByteString`` defined in ``collections.abc``<br>and a corresponding type in ``typing``, functions accepting bytes (of<br>some form) are so common that it would be cumbersome to have to write<br>``typing.ByteString`` everywhere.  So, as a shortcut similar to that<br>for the builtin numeric classes, when an argument is annotated as<br>having type ``bytes``, arguments of type ``bytearray`` or<br>``memoryview`` are acceptable.  (Again, there are situations where<br>this isn't sound, but we believe those are exceedingly rare in<br>practice.)<br><br><br>Forward references<br>------------------<br><br>When a type hint contains names that have not been defined yet, that<br>definition may be expressed as a string literal, to be resolved later.<br><br>A situation where this occurs commonly is the definition of a<br>container class, where the class being defined occurs in the signature<br>of some of the methods.  For example, the following code (the start of<br>a simple binary tree implementation) does not work::<br><br>  class Tree:<br>      def __init__(self, left: Tree, right: Tree):<br>          self.left = left<br>          self.right = right<br><br>To address this, we write::<br><br>  class Tree:<br>      def __init__(self, left: 'Tree', right: 'Tree'):<br>          self.left = left<br>          self.right = right<br><br>The string literal should contain a valid Python expression (i.e.,<br>``compile(lit, '', 'eval')`` should be a valid code object) and it<br>should evaluate without errors once the module has been fully loaded.<br>The local and global namespace in which it is evaluated should be the<br>same namespaces in which default arguments to the same function would<br>be evaluated.<br><br>Moreover, the expression should be parseable as a valid type hint, i.e.,<br>it is constrained by the rules from the section `Acceptable type hints`_<br>above.<br><br>It is allowable to use string literals as *part* of a type hint, for<br>example::<br><br>    class Tree:<br>        ...<br>        def leaves(self) -> List['Tree']:<br>            ...<br><br>A common use for forward references is when e.g. Django models are<br>needed in the signatures.  Typically, each model is in a separate<br>file, and has methods that arguments whose type involves other models.<br>Because of the way circular imports work in Python, it is often not<br>possible to import all the needed models directly::<br><br>    # File models/a.py<br>    from models.b import B<br>    class A(Model):<br>        def foo(self, b: B): ...<br><br>    # File models/b.py<br>    from models.a import A<br>    class B(Model):<br>        def bar(self, a: A): ...<br><br>    # File main.py<br>    from models.a import A<br>    from models.b import B<br><br>Assuming main is imported first, this will fail with an ImportError at<br>the line ``from models.a import A`` in models/b.py, which is being<br>imported from models/a.py before a has defined class A.  The solution<br>is to switch to module-only imports and reference the models by their<br>_module_._class_ name::<br><br>    # File models/a.py<br>    from models import b<br>    class A(Model):<br>        def foo(self, b: 'b.B'): ...<br><br>    # File models/b.py<br>    from models import a<br>    class B(Model):<br>        def bar(self, a: 'a.A'): ...<br><br>    # File main.py<br>    from models.a import A<br>    from models.b import B<br><br><br>Union types<br>-----------<br><br>Since accepting a small, limited set of expected types for a single<br>argument is common, there is a new special factory called ``Union``.<br>Example::<br><br>  from typing import Union<br><br>  def handle_employees(e: Union[Employee, Sequence[Employee]]) -> None:<br>      if isinstance(e, Employee):<br>          e = [e]<br>      ...<br><br>A type factored by ``Union[T1, T2, ...]`` responds ``True`` to<br>``issubclass`` checks for ``T1`` and any of its subtypes, ``T2`` and<br>any of its subtypes, and so on.<br><br>One common case of union types are *optional* types.  By default,<br>``None`` is an invalid value for any type, unless a default value of<br>``None`` has been provided in the function definition.  Examples::<br><br>  def handle_employee(e: Union[Employee, None]) -> None: ...<br><br>As a shorthand for ``Union[T1, None]`` you can write ``Optional[T1]``;<br>for example, the above is equivalent to::<br><br>  from typing import Optional<br><br>  def handle_employee(e: Optional[Employee]) -> None: ...<br><br>An optional type is also automatically assumed when the default value is<br>``None``, for example::<br><br>  def handle_employee(e: Employee = None): ...<br><br>This is equivalent to::<br><br>  def handle_employee(e: Optional[Employee] = None) -> None: ...<br><br>The ``Any`` type<br>----------------<br><br>A special kind of type is ``Any``.  Every type is a subtype of<br>``Any``.  This is also true for the builtin type ``object``.<br>However, to the static type checker these are completely different.<br><br>When the type of a value is ``object``, the type checker will reject<br>almost all operations on it, and assigning it to a variable (or using<br>it as a return value) of a more specialized type is a type error.  On<br>the other hand, when a value has type ``Any``, the type checker will<br>allow all operations on it, and a value of type ``Any`` can be assigned<br>to a variable (or used as a return value) of a more constrained type.<br><br><br>Version and platform checking<br>-----------------------------<br><br>Type checkers are expected to understand simple version and platform<br>checks, e.g.::<br><br>  import sys<br><br>  if sys.version_info[0] >= 3:<br>      # Python 3 specific definitions<br>  else:<br>      # Python 2 specific definitions<br><br>  if sys.platform == 'win32':<br>      # Windows specific definitions<br>  else:<br>      # Posix specific definitions<br><br>Don't expect a checker to understand obfuscations like<br>``"".join(reversed(sys.platform)) == "xunil"``.<br><br><br>Default argument values<br>-----------------------<br><br>In stubs it may be useful to declare an argument as having a default<br>without specifying the actual default value.  For example::<br><br>  def foo(x: AnyStr, y: AnyStr = ...) -> AnyStr: ...<br><br>What should the default value look like?  Any of the options ``""``,<br>``b""`` or ``None`` fails to satisfy the type constraint (actually,<br>``None`` will *modify* the type to become ``Optional[AnyStr]``).<br><br>In such cases the default value may be specified as a literal<br>ellipsis, i.e. the above example is literally what you would write.<br><br><br>Compatibility with other uses of function annotations<br>=====================================================<br><br>A number of existing or potential use cases for function annotations<br>exist, which are incompatible with type hinting.  These may confuse<br>a static type checker.  However, since type hinting annotations have no<br>runtime behavior (other than evaluation of the annotation expression and<br>storing annotations in the ``__annotations__`` attribute of the function<br>object), this does not make the program incorrect -- it just may cause<br>a type checker to emit spurious warnings or errors.<br><br>To mark portions of the program that should not be covered by type<br>hinting, you can use one or more of the following:<br><br>* a ``# type: ignore`` comment;<br><br>* a ``@no_type_check`` decorator on a class or function;<br><br>* a custom class or function decorator marked with<br>  ``@no_type_check_decorator``.<br><br>For more details see later sections.<br><br>In order for maximal compatibility with offline type checking it may<br>eventually be a good idea to change interfaces that rely on annotations<br>to switch to a different mechanism, for example a decorator.  In Python<br>3.5 there is no pressure to do this, however.  See also the longer<br>discussion under `Rejected alternatives`_ below.<br><br><br>Type comments<br>=============<br><br>No first-class syntax support for explicitly marking variables as being<br>of a specific type is added by this PEP.  To help with type inference in<br>complex cases, a comment of the following format may be used::<br><br>  x = []   # type: List[Employee]<br>  x, y, z = [], [], []  # type: List[int], List[int], List[str]<br>  x, y, z = [], [], []  # type: (List[int], List[int], List[str])<br>  x = [<br>     1,<br>     2,<br>  ]  # type: List[int]<br><br>Type comments should be put on the last line of the statement that<br>contains the variable definition. They can also be placed on<br>``with`` statements and ``for`` statements, right after the colon.<br><br>Examples of type comments on ``with`` and ``for`` statements::<br><br>  with frobnicate() as foo:  # type: int<br>      # Here foo is an int<br>      ...<br><br>  for x, y in points:  # type: float, float<br>      # Here x and y are floats<br>      ...<br><br>In stubs it may be useful to declare the existence of a variable<br>without giving it an initial value.  This can be done using a literal<br>ellipsis::<br><br>  from typing import IO<br><br>  stream = ...  # type: IO[str]<br><br>In non-stub code, there is a similar special case:<br><br>  from typing import IO<br><br>  stream = None  # type: IO[str]<br><br>Type checkers should not complain about this (despite the value<br>``None`` not matching the given type), nor should they change the<br>inferred type to ``Optional[...]`` (despite the rule that does this<br>for annotated arguments with a default value of ``None``).  The<br>assumption here is that other code will ensure that the variable is<br>given a value of the proper type, and all uses can assume that the<br>variable has the given type.<br><br>The ``# type: ignore`` comment should be put on the line that the<br>error refers to::<br><br>  import http.client<br>  errors = {<br>      'not_found': http.client.NOT_FOUND  # type: ignore<br>  }<br><br>A ``# type: ignore`` comment on a line by itself disables all type<br>checking for the rest of the file.<br><br>If type hinting proves useful in general, a syntax for typing variables<br>may be provided in a future Python version.<br><br>Casts<br>=====<br><br>Occasionally the type checker may need a different kind of hint: the<br>programmer may know that an expression is of a more constrained type<br>than a type checker may be able to infer.  For example::<br><br>  from typing import List, cast<br><br>  def find_first_str(a: List[object]) -> str:<br>      index = next(i for i, x in enumerate(a) if isinstance(x, str))<br>      # We only get here if there's at least one string in a<br>      return cast(str, a[index])<br><br>Some type checkers may not be able to infer that the type of<br>``a[index]`` is ``str`` and only infer ``object`` or ``Any``", but we<br>know that (if the code gets to that point) it must be a string.  The<br>``cast(t, x)`` call tells the type checker that we are confident that<br>the type of ``x`` is ``t``.  At runtime a cast always returns the<br>expression unchanged -- it does not check the type, and it does not<br>convert or coerce the value.<br><br>Casts differ from type comments (see the previous section).  When using<br>a type comment, the type checker should still verify that the inferred<br>type is consistent with the stated type.  When using a cast, the type<br>checker should blindly believe the programmer.  Also, casts can be used<br>in expressions, while type comments only apply to assignments.<br><br><br>Stub Files<br>==========<br><br>Stub files are files containing type hints that are only for use by<br>the type checker, not at runtime.  There are several use cases for<br>stub files:<br><br>* Extension modules<br><br>* Third-party modules whose authors have not yet added type hints<br><br>* Standard library modules for which type hints have not yet been<br>  written<br><br>* Modules that must be compatible with Python 2 and 3<br><br>* Modules that use annotations for other purposes<br><br>Stub files have the same syntax as regular Python modules.  There is one<br>feature of the ``typing`` module that may only be used in stub files:<br>the ``@overload`` decorator described below.<br><br>The type checker should only check function signatures in stub files;<br>It is recommended that function bodies in stub files just be a single<br>ellipsis (``...``).<br><br>The type checker should have a configurable search path for stub files.<br>If a stub file is found the type checker should not read the<br>corresponding "real" module.<br><br>While stub files are syntactically valid Python modules, they use the<br>``.pyi`` extension to make it possible to maintain stub files in the<br>same directory as the corresponding real module.  This also reinforces<br>the notion that no runtime behavior should be expected of stub files.<br><br>Additional notes on stub files:<br><br>* Modules and variables imported into the stub are not considered<br>  exported from the stub unless the import uses the ``import ... as<br>  ...`` form.<br><br>Function overloading<br>--------------------<br><br>The ``@overload`` decorator allows describing functions that support<br>multiple different combinations of argument types.  This pattern is<br>used frequently in builtin modules and types.  For example, the<br>``__getitem__()`` method of the ``bytes`` type can be described as<br>follows::<br><br>  from typing import overload<br><br>  class bytes:<br>      ...<br>      @overload<br>      def __getitem__(self, i: int) -> int: ...<br>      @overload<br>      def __getitem__(self, s: slice) -> bytes: ...<br><br>This description is more precise than would be possible using unions<br>(which cannot express the relationship between the argument and return<br>types)::<br><br>  from typing import Union<br><br>  class bytes:<br>      ...<br>      def __getitem__(self, a: Union[int, slice]) -> Union[int, bytes]: ...<br><br>Another example where ``@overload`` comes in handy is the type of the<br>builtin ``map()`` function, which takes a different number of<br>arguments depending on the type of the callable::<br><br>  from typing import Callable, Iterable, Iterator, Tuple, TypeVar, overload<br><br>  T1 = TypeVar('T1')<br>  T2 = TypeVar('T2)<br>  S = TypeVar('S')<br><br>  @overload<br>  def map(func: Callable[[T1], S], iter1: Iterable[T1]) -> Iterator[S]: ...<br>  @overload<br>  def map(func: Callable[[T1, T2], S],<br>          iter1: Iterable[T1], iter2: Iterable[T2]) -> Iterator[S]: ...<br>  # ... and we could add more items to support more than two iterables<br><br>Note that we could also easily add items to support ``map(None, ...)``::<br><br>  @overload<br>  def map(func: None, iter1: Iterable[T1]) -> Iterable[T1]: ...<br>  @overload<br>  def map(func: None,<br>          iter1: Iterable[T1],<br>          iter2: Iterable[T2]) -> Iterable[Tuple[T1, T2]]: ...<br><br>The ``@overload`` decorator may only be used in stub files.  While it<br>would be possible to provide a multiple dispatch implementation using<br>this syntax, its implementation would require using<br>``sys._getframe()``, which is frowned upon.  Also, designing and<br>implementing an efficient multiple dispatch mechanism is hard, which<br>is why previous attempts were abandoned in favor of<br>``functools.singledispatch()``.  (See PEP 443, especially its section<br>"Alternative approaches".)  In the future we may come up with a<br>satisfactory multiple dispatch design, but we don't want such a design<br>to be constrained by the overloading syntax defined for type hints in<br>stub files.  In the meantime, using the ``@overload`` decorator or<br>calling ``overload()`` directly raises ``RuntimeError``.<br><br>A constrained ``TypeVar`` type can often be used instead of using the<br>``@overload`` decorator.  For example, the definitions of ``concat1``<br>and ``concat2`` in this stub file are equivalent:<br><br>  from typing import TypeVar<br><br>  AnyStr = TypeVar('AnyStr', str, bytes)<br><br>  def concat1(x: AnyStr, y: AnyStr) -> AnyStr: ...<br><br>  @overload<br>  def concat2(x: str, y: str) -> str: ...<br>  @overload<br>  def concat2(x: bytes, y: bytes) -> bytes: ...<br><br>Some functions, such as ``map`` or ``bytes.__getitem__`` above, can't<br>be represented precisely using type variables.  However, unlike<br>``@overload``, type variables can also be used outside stub files.  We<br>recommend that ``@overload`` is only used in cases where a type<br>variable is not sufficient, due to its special stub-only status.<br><br>Another important difference between type variables such as ``AnyStr``<br>and using ``@overload`` is that the prior can also be used to define<br>constraints for generic class type parameters.  For example, the type<br>parameter of the generic class ``typing.IO`` is constrained (only<br>``IO[str]``, ``IO[bytes]`` and ``IO[Any]`` are valid):<br><br>  class IO(Generic[AnyStr]): ...<br><br>Storing and distributing stub files<br>-----------------------------------<br><br>The easiest form of stub file storage and distribution is to put them<br>alongside Python modules in the same directory.  This makes them easy to<br>find by both programmers and the tools.  However, since package<br>maintainers are free not to add type hinting to their packages,<br>third-party stubs installable by ``pip`` from PyPI are also supported.<br>In this case we have to consider three issues: naming, versioning,<br>installation path.<br><br>This PEP does not provide a recommendation on a naming scheme that<br>should be used for third-party stub file packages.  Discoverability will<br>hopefully be based on package popularity, like with Django packages for<br>example.<br><br>Third-party stubs have to be versioned using the lowest version of the<br>source package that is compatible.  Example: FooPackage has versions<br>1.0, 1.1, 1.2, 1.3, 2.0, 2.1, 2.2.  There are API changes in versions<br>1.1, 2.0 and 2.2.  The stub file package maintainer is free to release<br>stubs for all versions but at least 1.0, 1.1, 2.0 and 2.2 are needed<br>to enable the end user type check all versions.  This is because the<br>user knows that the closest *lower or equal* version of stubs is<br>compatible.  In the provided example, for FooPackage 1.3 the user would<br>choose stubs version 1.1.<br><br>Note that if the user decides to use the "latest" available source<br>package, using the "latest" stub files should generally also work if<br>they're updated often.<br><br>Third-party stub packages can use any location for stub storage.  Type<br>checkers should search for them using PYTHONPATH.  A default fallback<br>directory that is always checked is ``shared/typehints/python3.5/`` (or<br>3.6, etc.).  Since there can only be one package installed for a given<br>Python version per environment, no additional versioning is performed<br>under that directory (just like bare directory installs by ``pip`` in<br>site-packages).  Stub file package authors might use the following<br>snippet in ``setup.py``::<br><br>  ...<br>  data_files=[<br>      (<br>          'shared/typehints/python{}.{}'.format(*sys.version_info[:2]),<br>          pathlib.Path(SRC_PATH).glob('**/*.pyi'),<br>      ),<br>  ],<br>  ...<br><br>The Typeshed Repo<br>-----------------<br><br>There is a shared repository where useful stubs are being collected<br>[typeshed]_.  Note that stubs for a given package will not be included<br>here without the explicit consent of the package owner.  Further<br>policies regarding the stubs collected here will be decided at a later<br>time, after discussion on python-dev, and reported in the typeshed<br>repo's README.<br><br><br>Exceptions<br>==========<br><br>No syntax for listing explicitly raised exceptions is proposed.<br>Currently the only known use case for this feature is documentational,<br>in which case the recommendation is to put this information in a<br>docstring.<br><br><br>The ``typing`` Module<br>=====================<br><br>To open the usage of static type checking to Python 3.5 as well as older<br>versions, a uniform namespace is required.  For this purpose, a new<br>module in the standard library is introduced called ``typing``.<br><br>It defines the fundamental building blocks for constructing types<br>(e.g. ``Any``), types representing generic variants of builtin<br>collections (e.g. ``List``), types representing generic<br>collection ABCs (e.g. ``Sequence``), and a small collection of<br>convenience definitions.<br><br>Fundamental building blocks:<br><br>* Any, used as ``def get(key: str) -> Any: ...``<br><br>* Union, used as ``Union[Type1, Type2, Type3]``<br><br>* Callable, used as ``Callable[[Arg1Type, Arg2Type], ReturnType]``<br><br>* Tuple, used by listing the element types, for example<br>  ``Tuple[int, int, str]``.<br>  Arbitrary-length homogeneous tuples can be expressed<br>  using one type and ellipsis, for example ``Tuple[int, ...]``.<br>  (The ``...`` here are part of the syntax, a literal ellipsis.)<br><br>* TypeVar, used as ``X = TypeVar('X', Type1, Type2, Type3)`` or simply<br>  ``Y = TypeVar('Y')`` (see above for more details)<br><br>* Generic, used to create user-defined generic classes<br><br>Generic variants of builtin collections:<br><br>* Dict, used as ``Dict[key_type, value_type]``<br><br>* List, used as ``List[element_type]``<br><br>* Set, used as ``Set[element_type]``. See remark for ``AbstractSet``<br>  below.<br><br>* FrozenSet, used as ``FrozenSet[element_type]``<br><br>Note: ``Dict``, ``List``, ``Set`` and ``FrozenSet`` are mainly useful<br>for annotating return values.  For arguments, prefer the abstract<br>collection types defined below, e.g.  ``Mapping``, ``Sequence`` or<br>``AbstractSet``.<br><br>Generic variants of container ABCs (and a few non-containers):<br><br>* ByteString<br><br>* Callable (see above, listed here for completeness)<br><br>* Container<br><br>* Generator, used as ``Generator[yield_type, send_type,<br>  return_type]``.  This represents the return value of generator<br>  functions.  It is a subtype of ``Iterable`` and it has additional<br>  type variables for the type accepted by the ``send()`` method (which<br>  is contravariant -- a generator that accepts sending it ``Employee``<br>  instance is valid in a context where a generator is required that<br>  accepts sending it ``Manager`` instances) and the return type of the<br>  generator.<br><br>* Hashable (not generic, but present for completeness)<br><br>* ItemsView<br><br>* Iterable<br><br>* Iterator<br><br>* KeysView<br><br>* Mapping<br><br>* MappingView<br><br>* MutableMapping<br><br>* MutableSequence<br><br>* MutableSet<br><br>* Sequence<br><br>* Set, renamed to ``AbstractSet``. This name change was required<br>  because ``Set`` in the ``typing`` module means ``set()`` with<br>  generics.<br><br>* Sized (not generic, but present for completeness)<br><br>* ValuesView<br><br>A few one-off types are defined that test for single special methods<br>(similar to ``Hashable`` or ``Sized``):<br><br>* Reversible, to test for ``__reversed__``<br><br>* SupportsAbs, to test for ``__abs__``<br><br>* SupportsComplex, to test for ``__complex__``<br><br>* SupportsFloat, to test for ``__float__``<br><br>* SupportsInt, to test for ``__int__``<br><br>* SupportsRound, to test for ``__round__``<br><br>* SupportsBytes, to test for ``__bytes__``<br><br>Convenience definitions:<br><br>* Optional, defined by ``Optional[t] == Union[t, type(None)]``<br><br>* AnyStr, defined as ``TypeVar('AnyStr', str, bytes)``<br><br>* NamedTuple, used as<br>  ``NamedTuple(type_name, [(field_name, field_type), ...])``<br>  and equivalent to<br>  ``collections.namedtuple(type_name, [field_name, ...])``.<br>  This is useful to declare the types of the fields of a a named tuple<br>  type.<br><br>* cast(), described earlier<br><br>* @no_type_check, a decorator to disable type checking per class or<br>  function (see below)<br><br>* @no_type_check_decorator, a decorator to create your own decorators<br>  with the same meaning as ``@no_type_check`` (see below)<br><br>* @overload, described earlier<br><br>* get_type_hints(), a utility function to retrieve the type hints from a<br>  function or method.  Given a function or method object, it returns<br>  a dict with the same format as ``__annotations__``, but evaluating<br>  forward references (which are given as string literals) as expressions<br>  in the context of the original function or method definition.<br><br>Types available in the ``<a href="http://typing.io">typing.io</a>`` submodule:<br><br>* IO (generic over ``AnyStr``)<br><br>* BinaryIO (a simple subtype of ``IO[bytes]``)<br><br>* TextIO (a simple subtype of ``IO[str]``)<br><br>Types available in the ``<a href="http://typing.re">typing.re</a>`` submodule:<br><br>* Match and Pattern, types of ``re.match()`` and ``re.compile()``<br>  results (generic over ``AnyStr``)<br><br><br>Rejected Alternatives<br>=====================<br><br>During discussion of earlier drafts of this PEP, various objections<br>were raised and alternatives were proposed.  We discuss some of these<br>here and explain why we reject them.<br><br>Several main objections were raised.<br><br>Which brackets for generic type parameters?<br>-------------------------------------------<br><br>Most people are familiar with the use of angular brackets<br>(e.g. ``List<int>``) in languages like C++, Java, C# and Swift to<br>express the parametrization of generic types.  The problem with these<br>is that they are really hard to parse, especially for a simple-minded<br>parser like Python.  In most languages the ambiguities are usually<br>dealt with by only allowing angular brackets in specific syntactic<br>positions, where general expressions aren't allowed.  (And also by<br>using very powerful parsing techniques that can backtrack over an<br>arbitrary section of code.)<br><br>But in Python, we'd like type expressions to be (syntactically) the<br>same as other expressions, so that we can use e.g. variable assignment<br>to create type aliases.  Consider this simple type expression::<br><br>    List<int><br><br>From the Python parser's perspective, the expression begins with the<br>same four tokens (NAME, LESS, NAME, GREATER) as a chained comparison::<br><br>    a < b > c  # I.e., (a < b) and (b > c)<br><br>We can even make up an example that could be parsed both ways::<br><br>    a < b > [ c ]<br><br>Assuming we had angular brackets in the language, this could be<br>interpreted as either of the following two::<br><br>    (a<b>)[c]      # I.e., (a<b>).__getitem__(c)<br>    a < b > ([c])  # I.e., (a < b) and (b > [c])<br><br>It would surely be possible to come up with a rule to disambiguate<br>such cases, but to most users the rules would feel arbitrary and<br>complex.  It would also require us to dramatically change the CPython<br>parser (and every other parser for Python).  It should be noted that<br>Python's current parser is intentionally "dumb" -- a simple grammar is<br>easier for users to reason about.<br><br>For all these reasons, square brackets (e.g. ``List[int]``) are (and<br>have long been) the preferred syntax for generic type parameters.<br>They can be implemented by defining the ``__getitem__()`` method on<br>the metaclass, and no new syntax is required at all.  This option<br>works in all recent versions of Python (starting with Python 2.2).<br>Python is not alone in this syntactic choice -- generic classes in<br>Scala also use square brackets.<br><br>What about existing uses of annotations?<br>----------------------------------------<br><br>One line of argument points out that PEP 3107 explicitly supports<br>the use of arbitrary expressions in function annotations.  The new<br>proposal is then considered incompatible with the specification of PEP<br>3107.<br><br>Our response to this is that, first of all, the current proposal does<br>not introduce any direct incompatibilities, so programs using<br>annotations in Python 3.4 will still work correctly and without<br>prejudice in Python 3.5.<br><br>We do hope that type hints will eventually become the sole use for<br>annotations, but this will require additional discussion and a<br>deprecation period after the initial roll-out of the typing module<br>with Python 3.5.  The current PEP will have provisional status (see<br>PEP 411) until Python 3.6 is released.  The fastest conceivable scheme<br>would introduce silent deprecation of non-type-hint annotations in<br>3.6, full deprecation in 3.7, and declare type hints as the only<br>allowed use of annotations in Python 3.8.  This should give authors of<br>packages that use annotations plenty of time to devise another<br>approach, even if type hints become an overnight success.<br><br>Another possible outcome would be that type hints will eventually<br>become the default meaning for annotations, but that there will always<br>remain an option to disable them.  For this purpose the current<br>proposal defines a decorator ``@no_type_check`` which disables the<br>default interpretation of annotations as type hints in a given class<br>or function.  It also defines a meta-decorator<br>``@no_type_check_decorator`` which can be used to decorate a decorator<br>(!), causing annotations in any function or class decorated with the<br>latter to be ignored by the type checker.<br><br>There are also ``# type: ignore`` comments, and static checkers should<br>support configuration options to disable type checking in selected<br>packages.<br><br>Despite all these options, proposals have been circulated to allow<br>type hints and other forms of annotations to coexist for individual<br>arguments.  One proposal suggests that if an annotation for a given<br>argument is a dictionary literal, each key represents a different form<br>of annotation, and the key ``'type'`` would be use for type hints.<br>The problem with this idea and its variants is that the notation<br>becomes very "noisy" and hard to read.  Also, in most cases where<br>existing libraries use annotations, there would be little need to<br>combine them with type hints.  So the simpler approach of selectively<br>disabling type hints appears sufficient.<br><br>The problem of forward declarations<br>-----------------------------------<br><br>The current proposal is admittedly sub-optimal when type hints must<br>contain forward references.  Python requires all names to be defined<br>by the time they are used.  Apart from circular imports this is rarely<br>a problem: "use" here means "look up at runtime", and with most<br>"forward" references there is no problem in ensuring that a name is<br>defined before the function using it is called.<br><br>The problem with type hints is that annotations (per PEP 3107, and<br>similar to default values) are evaluated at the time a function is<br>defined, and thus any names used in an annotation must be already<br>defined when the function is being defined.  A common scenario is a<br>class definition whose methods need to reference the class itself in<br>their annotations.  (More general, it can also occur with mutually<br>recursive classes.)  This is natural for container types, for<br>example::<br><br>  class Node:<br>      """Binary tree node."""<br><br>      def __init__(self, left: Node, right: None):<br>          self.left = left<br>          self.right = right<br><br>As written this will not work, because of the peculiarity in Python<br>that class names become defined once the entire body of the class has<br>been executed.  Our solution, which isn't particularly elegant, but<br>gets the job done, is to allow using string literals in annotations.<br>Most of the time you won't have to use this though -- most *uses* of<br>type hints are expected to reference builtin types or types defined in<br>other modules.<br><br>A counterproposal would change the semantics of type hints so they<br>aren't evaluated at runtime at all (after all, type checking happens<br>off-line, so why would type hints need to be evaluated at runtime at<br>all).  This of course would run afoul of backwards compatibility,<br>since the Python interpreter doesn't actually know whether a<br>particular annotation is meant to be a type hint or something else.<br><br>A compromise is possible where a ``__future__`` import could enable<br>turning *all* annotations in a given module into string literals, as<br>follows::<br><br>  from __future__ import annotations<br><br>  class ImSet:<br>      def add(self, a: ImSet) -> List[ImSet]: ...<br><br>  assert ImSet.add.__annotations__ == {'a': 'ImSet', 'return': 'List[ImSet]'}<br><br>Such a ``__future__`` import statement may be proposed in a separate<br>PEP.<br><br><br>The double colon<br>----------------<br><br>A few creative souls have tried to invent solutions for this problem.<br>For example, it was proposed to use a double colon (``::``) for type<br>hints, solving two problems at once: disambiguating between type hints<br>and other annotations, and changing the semantics to preclude runtime<br>evaluation.  There are several things wrong with this idea, however.<br><br>* It's ugly.  The single colon in Python has many uses, and all of<br>  them look familiar because they resemble the use of the colon in<br>  English text.  This is a general rule of thumb by which Python<br>  abides for most forms of punctuation; the exceptions are typically<br>  well known from other programming languages.  But this use of ``::``<br>  is unheard of in English, and in other languages (e.g. C++) it is<br>  used as a scoping operator, which is a very different beast.  In<br>  contrast, the single colon for type hints reads naturally -- and no<br>  wonder, since it was carefully designed for this purpose (the idea<br>  long predates PEP 3107 [gvr-artima]_).  It is also used in the same<br>  fashion in other languages from Pascal to Swift.<br><br>* What would you do for return type annotations?<br><br>* It's actually a feature that type hints are evaluated at runtime.<br><br>  * Making type hints available at runtime allows runtime type<br>    checkers to be built on top of type hints.<br><br>  * It catches mistakes even when the type checker is not run.  Since<br>    it is a separate program, users may choose not to run it (or even<br>    install it), but might still want to use type hints as a concise<br>    form of documentation.  Broken type hints are no use even for<br>    documentation.<br><br>* Because it's new syntax, using the double colon for type hints would<br>  limit them to code that works with Python 3.5 only.  By using<br>  existing syntax, the current proposal can easily work for older<br>  versions of Python 3.  (And in fact mypy supports Python 3.2 and<br>  newer.)<br><br>* If type hints become successful we may well decide to add new syntax<br>  in the future to declare the type for variables, for example<br>  ``var age: int = 42``.  If we were to use a double colon for<br>  argument type hints, for consistency we'd have to use the same<br>  convention for future syntax, perpetuating the ugliness.<br><br>Other forms of new syntax<br>-------------------------<br><br>A few other forms of alternative syntax have been proposed, e.g. the<br>introduction of a ``where`` keyword [roberge]_, and Cobra-inspired<br>``requires`` clauses.  But these all share a problem with the double<br>colon: they won't work for earlier versions of Python 3.  The same<br>would apply to a new ``__future__`` import.<br><br>Other backwards compatible conventions<br>--------------------------------------<br><br>The ideas put forward include:<br><br>* A decorator, e.g. ``@typehints(name=str, returns=str)``.  This could<br>  work, but it's pretty verbose (an extra line, and the argument names<br>  must be repeated), and a far cry in elegance from the PEP 3107<br>  notation.<br><br>* Stub files.  We do want stub files, but they are primarily useful<br>  for adding type hints to existing code that doesn't lend itself to<br>  adding type hints, e.g. 3rd party packages, code that needs to<br>  support both Python 2 and Python 3, and especially extension<br>  modules.  For most situations, having the annotations in line with<br>  the function definitions makes them much more useful.<br><br>* Docstrings.  There is an existing convention for docstrings, based<br>  on the Sphinx notation (``:type arg1: description``).  This is<br>  pretty verbose (an extra line per parameter), and not very elegant.<br>  We could also make up something new, but the annotation syntax is<br>  hard to beat (because it was designed for this very purpose).<br><br>It's also been proposed to simply wait another release.  But what<br>problem would that solve?  It would just be procrastination.<br><br><br>PEP Development Process<br>=======================<br><br>A live draft for this PEP lives on GitHub [github]_.  There is also an<br>issue tracker [issues]_, where much of the technical discussion takes<br>place.<br><br>The draft on GitHub is updated regularly in small increments.  The<br>official PEPS repo [peps_] is (usually) only updated when a new draft<br>is posted to python-dev.<br><br><br>Acknowledgements<br>================<br><br>This document could not be completed without valuable input,<br>encouragement and advice from Jim Baker, Jeremy Siek, Michael Matson<br>Vitousek, Andrey Vlasovskikh, Radomir Dopieralski, Peter Ludemann,<br>and the BDFL-Delegate, Mark Shannon.<br><br>Influences include existing languages, libraries and frameworks<br>mentioned in PEP 482.  Many thanks to their creators, in alphabetical<br>order: Stefan Behnel, William Edwards, Greg Ewing, Larry Hastings,<br>Anders Hejlsberg, Alok Menghrajani, Travis E. Oliphant, Joe Pamer,<br>Raoul-Gabriel Urma, and Julien Verlaguet.<br><br><br>References<br>==========<br><br>.. [mypy]<br>   <a href="http://mypy-lang.org">http://mypy-lang.org</a><br><br>.. [gvr-artima]<br>   <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=85551">http://www.artima.com/weblogs/viewpost.jsp?thread=85551</a><br><br>.. [wiki-variance]<br>   <a href="http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29">http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29</a><br><br>.. [typeshed]<br>   <a href="https://github.com/JukkaL/typeshed/">https://github.com/JukkaL/typeshed/</a><br><br>.. [pyflakes]<br>   <a href="https://github.com/pyflakes/pyflakes/">https://github.com/pyflakes/pyflakes/</a><br><br>.. [pylint]<br>   <a href="http://www.pylint.org">http://www.pylint.org</a><br><br>.. [roberge]<br>   <a href="http://aroberge.blogspot.com/2015/01/type-hinting-in-python-focus-on.html">http://aroberge.blogspot.com/2015/01/type-hinting-in-python-focus-on.html</a><br><br>.. [github]<br>   <a href="https://github.com/ambv/typehinting">https://github.com/ambv/typehinting</a><br><br>.. [issues]<br>   <a href="https://github.com/ambv/typehinting/issues">https://github.com/ambv/typehinting/issues</a><br><br>.. [peps]<br>   <a href="https://hg.python.org/peps/file/tip/pep-0484.txt">https://hg.python.org/peps/file/tip/pep-0484.txt</a><br><br><br>Copyright<br>=========<br><br>This document has been placed in the public domain.<br><br><br> <br>..<br>   Local Variables:<br>   mode: indented-text<br>   indent-tabs-mode: nil<br>   sentence-end-double-space: t<br>   fill-column: 70<br>   coding: utf-8<br>   End:<br><br>-- <br><div class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div></div></div></div></div>