A typed world that begins with Python

Starting with Python 3.5, a feature called Type Hints has been introduced.

This is a specification that allows you to add type annotations (type annotations), and specifically looks like the following (Abstract Quoted from 0484 / # abstract)).

def greeting(name: str) -> str:
    return 'Hello ' + name

The following part is actually annotating.

Type Hints also mentions Type Comments in Variable Declarations (https://www.python.org/dev/peps/pep-0484/#type-comments).

x = []   # type: List[Employee]

This is really an extension of the comment, not the syntax, but if you're already commenting on these types, you can hijack the above notation and in the future you'll be able to type-check with some tool. There is a possibility.

This is the typed world that was introduced in Python.

Note that the added annotation is not checked at runtime. In short, it is an extension of the comment. Therefore, it is not enforceable, but it does nothing at runtime and does not affect performance.

Therefore, in principle, the syntax is for static analysis, but annotation information in typing.get_type_hints I think it is possible to implement run-time checking on your own (for example, type annotations).

Annotation notation

I would like to introduce the annotation notation along with typing.

Type aliases

It is possible to define type aliases.

Type aliases

Vector = List[float]

However, in my personal experience, this can be confusing (it's hard to tell if it's a class or an alias), so be careful about where you use it and how you name it.

Callable

This is a summary of function argument / return type definitions. It is used when a function is an argument like a callback function, or when a function is returned.

The notation is Callable ([argument type], return type). The following is an example of annotating feeder / async_query that takes a function as an argument with Callable.

Callable

from typing import Callable

def feeder(get_next_item: Callable[[], str]) -> None:
    # Body

def async_query(on_success: Callable[[int], None],
                on_error: Callable[[int, Exception], None]) -> None:
    # Body

Generics

So-called Generics are also available. You can write List <T> in Java etc. as follows.

Generics

from typing import Sequence, TypeVar

T = TypeVar('T')      # Declare type variable

def first(l: Sequence[T]) -> T:   # Generic function
    return l[0]

You can also limit the valid types of Generics with TypeVar. In the following, only str and bytes are allowed as AnyStr.

pep-0484/#generics

from typing import TypeVar

AnyStr = TypeVar('AnyStr', str, bytes)

def concat(x: AnyStr, y: AnyStr) -> AnyStr:
    return x + y

User-defined generic types

In the so-called Generics class, if you want to do something like MyClass <T>, define it as follows.

User-defined generic types

from typing import TypeVar, Generic

T = TypeVar('T')

class LoggedVar(Generic[T]):
    def __init__(self, value: T, name: str, logger: Logger) -> None:
        self.name = name
        self.logger = logger
        self.value = value

    def set(self, new: T) -> None:
        self.log('Set ' + repr(self.value))
        self.value = new

    def get(self) -> T:
        self.log('Get ' + repr(self.value))
        return self.value

    def log(self, message: str) -> None:
        self.logger.info('{}: {}'.format(self.name message))

Now you can use it like this:

from typing import Iterable

def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
    for var in vars:
        var.set(0)

The Any type

All types are subtypes of ʻAny. Note that ʻAny is different from ʻobject` in the class.

Union types

It is a collection of several acceptable types. ʻOptional is a kind of this ʻUnion.

Union types

from typing import Union

def handle_employee(e: Union[Employee, None]) -> None: ...

This is synonymous with:

from typing import Optional

def handle_employee(e: Optional[Employee]) -> None: ...

Method for checking

As mentioned above, I think the type annotation notation covers most of the scenes you want to type. However, as it is, it is the same as a comment, and even if you ignore the annotation you added, you will not notice it.

The Python standard does not provide an official tool for checking type annotations (as of 3.5). Therefore, you need to use an external tool for checking.

One type of this tool is mypy.

mypy

It was developed by Jukka, who is also the author of typehinting of Python itself, and I think it can be said that it is the de facto standard library for type annotation.

For checks in an integrated development environment, PyCharm has some support. In the following, the warning is where a numerical value is passed to greeting which takes str as an argument.

image

PyCharm originally supports annotations in docstrings and comments and will take over the standard in the future Can be expected to be added.

Visual Studio's Python Development Environment (PTVS) is said to be okay because it originally has strong type inference, but it seems that the inclusion of notation is being discussed.

Use type hints in Python 3.x to infer variable types if possible #82

install mypy

Here, we will introduce the installation procedure for checking using mypy.

You can install mypy from pip.

pip install mypy

~~ * Note that pip install mypy will include a completely different library ~~ From mypy 0.470, the library name has been changed from mypy-lang to mypy

Of course, it is premised on Python 3 (it is ok even if it is not 3.5), but [Python 2 will also be supported](http://mypy.readthedocs.org/en/latest/faq.html#all-of-my-code -is-still-in-python-2-what-are-my-options). As of November 2, 2015, if you want to use mypy with Python3.5, you need to install it from master. This is because the support for ʻUndefined`, which was removed in Python 3.5, has not yet been reflected in pypi (issue 639. ).

To pip install from GitHub master, do the following:

pip install git+https://github.com/JukkaL/mypy.git@master

Use of mypy

It is as per the official Quick Start, but you can run the check with the mypy command that will be available after installation.

mypy PROGRAM

If that doesn't work, please refer to Troubleshooting. The basics are covered here.

When you actually execute it, the execution result will be as follows.

>>> mypy examples/basic.py
examples\basic.py:5: error: Argument 1 to "greeting" has incompatible type "int"; expected "str"

You can also specify the module with the -m option.

>>> mypy -m examples
examples\__init__.py:1: note: In module imported here:
examples\basic.py:5: error: Argument 1 to "greeting" has incompatible type "int"; expected "str"

Here, ʻexamples / __ init __. Py` is as follows.

import examples.basic

As the check says "ʻIn module imported here: ", when targeting packages, it seems that anything that does not follow from __ init __. Py` is not checked. So be careful if you want to check all the files in the module.

As for existing libraries, it is not possible to annotate the source code of the contents and go around, so it is also possible to cut out the type definition to the outside and define it. A file that describes only this type definition is called a stub file, and its extension is pyi (TypeScript d.ts image).

If you want to read the pyi file prepared by mypy, set MYPYPATH.

export MYPYPATH=~/work/myproject/stubs

If you use the --use-python-path option, the ones in PYTHONPATH will be referenced.

Currently, there is no such thing as a type definition management tool like tsd in TypeScript, but [python / typeshed](https://github. It seems that aggregation is done to com / python / typeshed) (although there are not many yet).

For more details, please refer to the Official Document.

Introduction policy

The following points can be expected as the effects of introducing TypeHints.

And I think that the applicable targets are roughly as follows.

The following patterns can be considered as the method of introducing annotations for the specified target.

When introducing it, I think it is necessary to first clarify what kind of benefits you expect. If this is not clear, the criteria for application and implementation will be ambiguous.

This area is undergoing trial and error, including whether the expected effect can be obtained in the first place, so I would like to add it when know-how is accumulated again.

Reference material

Recommended Posts

A typed world that begins with Python
[Python] A program that creates stairs with #
Make a fortune with Python
A server that echoes data POSTed with flask / python
A memo that I touched the Datastore with python
Create a directory with python
Python starting with Hello world!
A memo that reads data from dashDB with Python & Spark
Use a macro that runs when saving python with vscode
Solve ABC163 A ~ C with Python
Operate a receipt printer with python
A python graphing manual with Matplotlib.
Let's make a GUI with python.
Solve ABC166 A ~ D with Python
Create a virtual environment with Python!
I made a fortune with Python.
Building a virtual environment with Python 3
Solve ABC168 A ~ C with Python
[Note] Hello world output with python
[Python] Generate a password with Slackbot
Solve ABC162 A ~ C with Python
Solve ABC167 A ~ C with Python
Solve ABC158 A ~ C with Python
Let's make a graph with python! !!
[Python] Inherit a class with class variables
I made a daemon with Python
Write a batch script with Python3.5 ~
[Python] Make a graph that can be moved around with Plotly
I made a package that can compare morphological analyzers with Python
I want to use a wildcard that I want to shell with Python remove
[Python] A memo that I tried to get started with asyncio
I made a shuffle that can be reset (reverted) with Python
The story of making a module that skips mail with python
[Pyenv] Building a python environment with ubuntu 16.04
Spiral book in Python! Python with a spiral book! (Chapter 14 ~)
Create a Python function decorator with Class
Creating a simple PowerPoint file with Python
Building a Python3 environment with Amazon Linux2
Let's make a shiritori game with Python
Install Python as a Framework with pyenv
Build a blockchain with Python ① Create a class
Add a Python data source with Redash
I made a character counter with Python
[Python] Drawing a swirl pattern with turtle
I drew a heatmap with seaborn [Python]
[Python] Create a virtual environment with Anaconda
Let's create a free group with Python
A memo with Python2.7 and Python3 on CentOS
Building a Python 3.6 environment with Windows + PowerShell
Map rent information on a map with python
Search the maze with the python A * algorithm
Let's make a voice slowly with Python
Created a darts trip with python (news)
[Python] A quick web application with Bottle!
[AtCoder] Solve ABC1 ~ 100 A problem with Python
Write a TCP client with Python Twisted
What I did with a Python array
Solve AtCoder ABC168 with python (A ~ D)
Create a word frequency counter with Python 3.4
Try HTML scraping with a Python library
Visualize point P that works with Python