What are Type hints in Python 3.5
Question: One of the talked about features in `Python 3.5` is said to be `type hints`.

An example of `type hints` is mentioned in this
[article](http://lwn.net/Articles/650904/) and
[this](http://lwn.net/Articles/640359/) while also mentioning to use type
hints responsibly. Can someone explain more about it and when it should be
used and when not?


Answer: I would suggest reading [PEP 483](https://www.python.org/dev/peps/pep-0483/)
and [PEP 484](https://www.python.org/dev/peps/pep-0484/) and watching
[this](https://www.youtube.com/watch?v=2wDvzy6Hgxg) presentation by Guido on
Type Hinting. In addition, more examples on Type Hints can be found at their
[documentation topic](http://stackoverflow.com/documentation/python/1766/type-
hints#t=201607251908319482596).

**In a nutshell** : **Type hinting is _literally what it means_ , you hint the
type of the object(s) you're using**.

Due to the highly **dynamic** nature of Python, _inferring or checking the
type_ of an object being used is especially hard. This fact makes it hard for
developers to understand what exactly is going on in code they haven't written
and, most importantly, for type checking tools found in many IDEs [PyCharm,
PyDev come to mind] that are limited due to the fact that they don't have any
indicator of what type the objects are. As a result they resort to trying to
infer the type with (as mentioned in the presentation) around 50% success
rate.

* * *

To take two important slides from the Type Hinting presentation:

### **_Why Type Hints?_**

  1. **Helps Type Checkers:** By hinting at what type you want the object to be the type checker can easily detect if, for instance, you're passing an object with a type that isn't expected.
  2. **Helps with documentation:** A third person viewing your code will know what is expected where, ergo, how to use it without getting them `TypeErrors`. 
  3. **Helps IDEs develop more accurate and robust tools:** Development Environments will be better suited at suggesting appropriate methods when know what type your object is. You have probably experienced this with some IDE at some point, hitting the `.` and having methods/attributes pop up which aren't defined for an object.

### **_Why Static Type Checkers?_**

  * **Find bugs sooner** : This is self evident, I believe.
  * **The larger your project the more you need it** : Again, makes sense. Static languages offer a robustness and control that dynamic languages lack. The bigger and more complex your application becomes the more control and predictability (from a behavioral aspect) you require.
  * **Large teams are already running static analysis** : I'm guessing this verifies the first two points.

**As a closing note for this small introduction** : This is an **optional**
feature and from what I understand it has been introduced in order to reap
some of the benefits of static typing.

You generally **do not** need to worry about it and **definitely** don't need
to use it (especially in cases where you use Python as an auxiliary scripting
language). It should be helpful when developing large projects as _it offers
much needed robustness, control and additional debugging capabilities_.

* * *

## **Type Hinting with mypy** :

In order to make this answer more complete, I think a little demonstration
would be suitable. I'll be using [`mypy`](http://mypy-lang.org/), the library
which inspired Type Hints as they are presented in the PEP. This is mainly
written for anybody bumping into this question and wondering where to begin.

Before I do that let reiterate the following: [PEP
484](https://www.python.org/dev/peps/pep-0484/) doesn't enforce anything; it
is simply setting a direction for function annotations and proposing
guidelines for **how** type checking can/should be performed. You can annotate
your functions and hint as many things as you want; your scripts will still
run regardless of the presence of annotations.

Anyways, as noted in the PEP, hinting types should generally take three forms:

  * Function annotations. ([PEP 3107](https://www.python.org/dev/peps/pep-3107/))
  * Stub files for built-in/user modules. (Ideal future for type checking)
  * Special `# type: type` comments. (Complementing the first two forms)**

Additionally, you'll want to use type hints in conjunction with the new
[`typing`](https://docs.python.org/3/library/typing.html) module introduced
with `Py3.5`. The typing module will save your life in this situation; in it,
many (additional) ABCs are defined along with helper functions and decorators
for use in static checking. Most `ABCs` in `collections.abc` are included but
in a `Generic` form in order to allow subscription (by defining a
`__getitem__()` method).

For anyone interested in a more in-depth explanation of these, the [`mypy
documentation`](http://mypy.readthedocs.org/en/latest/) is written very nicely
and has a lot of code samples demonstrating/describing the functionality of
their checker; it is definitely worth a read.

### Function annotations and special comments:

First, it's interesting to observe some of the behavior we can get when using
special comments. Special `# type: type` comments can be added during variable
assignments to indicate the type of an object if one cannot be directly
inferred. Simple assignments are generally easily inferred but others, like
lists (with regard to their contents), cannot.

**Note:** If we want to use any derivative of `Containers` and need to specify
the contents for that container we **must** use the **_generic_** types from
the `typing` module. **These support indexing.**

    
    
    # generic List, supports indexing.
    from typing import List
    
    # In this case, the type is easily inferred as type: int.
    i = 0
    
    # Even though the type can be inferred as of type list
    # there is no way to know the contents of this list.
    # By using type: List[str] we indicate we want to use a list of strings.
    a = []  # type: List[str]
    
    # Appending an int to our list
    # is statically not correct.
    a.append(i)
    
    # Appending a string is fine.
    a.append("i")
    
    print(a)  # [0, 'i']
    

If we add these commands to a file and execute them with our interpreter,
everything works just fine and `print(a)` just prints the contents of list
`a`. The `# type` comments have been discarded, _treated as plain comments
which have no additional semantic meaning_.

By running this with `mypy`, on the other hand, we get the following responce:

    
    
    (Python3)jimmi@jim: mypy typeHintsCode.py
    typesInline.py:14: error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str"
    

Indicating that a list of `str` objects cannot contain an `int`, which,
statically speaking, is sound. This can be fixed by either abiding to the type
of `a` and only appending `str` objects or by changing the type of the
contents of `a` to indicate that any value is acceptable (Intuitively
performed with `List[Any]` after `Any` has been imported from `typing`).

Function annotations are added in the form `param_name : type` after each
parameter in your function signature and a return type is specified using the
`-> type` notation before the ending function colon; all annotations are
stored in the `__annotations__` attribute for that function in a handy
dictionary form. Using a trivial example (which doesn't require extra types
from the `typing` module):

    
    
    def annotated(x: int, y: str) -> bool:
        return x < y
    

The `annotated.__annotations__` attribute now has the following values:

    
    
    {'y': <class 'str'>, 'return': <class 'bool'>, 'x': <class 'int'>}
    

If we're a complete noobie, or we are familiar with `Py2.7` concepts and are
consequently unaware of the `TypeError` lurking in the comparison of
`annotated`, we can perform another static check, catch the error and save us
some trouble:

    
    
    (Python3)jimmi@jim: mypy typeHintsCode.py
    typeFunction.py: note: In function "annotated":
    typeFunction.py:2: error: Unsupported operand types for > ("str" and "int")
    

Among other things, calling the function with invalid arguments will also get
caught:

    
    
    annotated(20, 20)
    
    # mypy complains:
    typeHintsCode.py:4: error: Argument 2 to "annotated" has incompatible type "int"; expected "str"
    

These can be extended to basically any use-case and the errors caught extend
further than basic calls and operations. The types you can check for are
really flexible and I have merely given a small sneak peak of its potential. A
look in the `typing` module, the PEPs or the `mypy` docs will give you a more
comprehensive idea of the capabilities offered.

### Stub Files:

Stub files can be used in two different non mutually exclusive cases:

  * You need to type check a module for which you do not want to directly alter the function signatures
  * You want to write modules and have type-checking but additionally want to separate annotations from content.

What stub files (with an extension of `.pyi`) are is an annotated interface of
the module you are making/want to use. They contain the signatures of the
functions you want to type-check with the body of the functions discarded. To
get a feel of this, given a set of three random functions in a module named
`randfunc.py`:

    
    
    def message(s):
        print(s)
    
    def alterContents(myIterable):
        return [i for i in myIterable if i % 2 == 0]
    
    def combine(messageFunc, itFunc):
        messageFunc("Printing the Iterable")
        a = alterContents(range(1, 20))
        return set(a)
    

We can create a stub file `randfunc.pyi`, in which we can place some
restrictions if we wish to do so. The downside is that somebody viewing the
source without the stub won't really get that annotation assistance when
trying to understand what is supposed to be passed where.

Anyway, the structure of a stub file is pretty simplistic: Add all function
definitions with empty bodies (`pass` filled) and supply the annotations based
on your requirements. Here, let's assume we only want to work with `int` types
for our Containers.

    
    
    # Stub for randfucn.py
    from typing import Iterable, List, Set, Callable
    
    def message(s: str) -> None: pass
    
    def alterContents(myIterable: Iterable[int])-> List[int]: pass
    
    def combine(
        messageFunc: Callable[[str], Any],
        itFunc: Callable[[Iterable[int]], List[int]]
    )-> Set[int]: pass
    

The `combine` function gives an indication of why you might want to use
annotations in a different file, they some times clutter up the code and
reduce readability (big no-no for Python). You could of course use type
aliases but that sometime confuses more than it helps (so use them wisely).

* * *

This should get you familiarized with the basic concepts of Type Hints in
Python. Even though the type checker used has been `mypy` you should gradually
start to see more of them pop-up, some internally in IDEs
([**PyCharm**](http://blog.jetbrains.com/pycharm/2015/11/python-3-5-type-
hinting-in-pycharm-5/),) and others as standard python modules. I'll try and
add additional checkers/related packages in the following list when and if I
find them (or if suggested).

**_Checkers I know of_** :

  * [**Mypy**](http://mypy-lang.org/): as described here.
  * [**PyType**](https://github.com/google/pytype): By Google, uses different notation from what I gather, probably worth a look.

**_Related Packages/Projects_** :

  * [**typeshed:**](https://github.com/python/typeshed/) Official Python repo housing an assortment of stub files for the standard library. 

The `typeshed` project is actually one of the best places you can look to see
how type hinting might be used in a project of your own. Let's take as an
example [the `__init__` dunders of the `Counter`
class](https://github.com/python/typeshed/blob/master/stdlib/3/collections.pyi#L78)
in the corresponding `.pyi` file:

    
    
    class Counter(Dict[_T, int], Generic[_T]):
            @overload
            def __init__(self) -> None: ...
            @overload
            def __init__(self, Mapping: Mapping[_T, int]) -> None: ...
            @overload
            def __init__(self, iterable: Iterable[_T]) -> None: ...
    

[Where `_T = TypeVar('_T')` is used to define generic
classes](http://mypy.readthedocs.org/en/latest/generics.html#defining-generic-
classes). For the `Counter` class we can see that it can either take no
arguments in its initializer, get a single `Mapping` from any type to an `int`
_or_ take an `Iterable` of any type.

* * *

**Notice** : One thing I forgot to mention was that the `typing` module has
been introduced on a _provisional basis_. From **[PEP
411](https://www.python.org/dev/peps/pep-0411/)** :

> A provisional package may have its API modified prior to "graduating" into a
> "stable" state. On one hand, this state provides the package with the
> benefits of being formally part of the Python distribution. On the other
> hand, the core development team explicitly states that no promises are made
> with regards to the the stability of the package's API, which may change for
> the next release. While it is considered an unlikely outcome, such packages
> may even be removed from the standard library without a deprecation period
> if the concerns regarding their API or maintenance prove well-founded.

So take things here with a pinch of salt; I'm doubtfull it will be removed or
altered in significant ways but one can never know.

* * *

** Another topic altogether but valid in the scope of type-hints: [`PEP
526`](https://docs.python.org/3.6/whatsnew/3.6.html#pep-526-syntax-for-
variable-annotations) is an effort to replace `# type` comments by introducing
new syntax which allows users to annotate the type of variables in simple
`varname: type` statements.

