Better type at Python

7 November 2015

Rick Mak

Oursky

Python 3.5 Release

https://docs.python.org/3.5/whatsnew/3.5.html
Released on September 13, 2015, 2 months ago

New library modules introduced
typing: PEP 484 – Type Hints

The syntax introduced long ago, Dec-2006
PEP 3107 - Function Annotations

2

Your view on type

3

Get it working

import typing
pip install typing
4

Some code

import sys


class Person:
    def __init__(self, name, lang):
        self.name = name
        self.lang = lang


def greeting(man):
    print(hello(man.name))


def hello(name = 'nobody'):
    return 'Hello' + name


if __name__ == '__main__':
    p = Person(sys.argv[1], sys.argv[2])
    greeting(p)
5

Same code with type hints

import sys


class Person:
    def __init__(self, name: str, lang: str) -> None:
        self.name = name
        self.lang = lang


def greeting(man: Person) -> None:
    print(hello(man.name))


def hello(name: str = 'nobody') -> str:
    return 'Hello' + name


if __name__ == '__main__':
    p = Person(sys.argv[1], sys.argv[2])
    greeting(p)
6

More complex type hints

Dictionary

from typing import Dict


def inc(d: Dict[str, int]) -> Dict[str, int]:
    for k in d.keys():
        d[k] = d[k] + 1
    return d

print(inc({
    'a': 1,
    'b': 2,
    'c': 3
}))
7

More complex type hints

Sequence and List

from typing import Sequence, List, TypeVar

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

def pick_odd(s: Sequence[T]) -> List[T]:
    len_ = len(s)
    list_ = []  # type: List
    for i in range(0, len_):
        if i % 2 == 1:
            list_.append(s[i])
    return list_

print(pick_odd([0,1,2,3,4,5,6,7]))
print(pick_odd('abcdefg'))
8

Forward references

class Human:
    def __init__(self, father: 'Human' = None, mother: 'Human' = None) -> None:
        self.father = father
        self.mother = mother

    def make(self, couple: 'Human') -> 'Human':
        return Human(self, couple)


print(Human())
9

What are type hints good for?

10

Make IDE works better

11

Let see how PyCharm works

12

Make development of static analysis tools easier

13

mypy

JukkaL/mypy

pip install mypy-lang

Analyse a file without running it

(venv)$ mypy callee.py
callee.py, line 7: Argument 1 to "hello" has incompatible type "int"; expected "str"
14

Serve as (additional) documentation

15

Docstring for sphinx to gen autodoc

def hello(name='nobody'):
    """Say hello to a person

    :param name: string value
    :rtype: string value
    """
    return 'Hello' + name
16

Same information using func type annotation

def hello(name: str = 'nobody') -> str:
    '''Say hello to a person
    '''
    return 'Hello' + name
17

Python2 with pyi stub

An *.pyi file that only have interface

def greeting(name: str) -> None: ...
def hello(name: str) -> str: ...

Also useful for
- Package you can't change
- Legacy package you don't want to change

There is github repos hosting stub for stdlib
python/typeshed

18

What type hints are not

19

How you can find out function annotation in your code

You can use inspect to get back the annotation.

import inspect
print(inspect.getfullargspec(inc).annotations)
'''
{
    'd': typing.Dict[str, int],
    'return': typing.Dict[str, int]
}
'''
print(inspect.getfullargspec(Human.make).annotations)
'''
{
    'return': 'Human',
    'couple': 'Human'
}
'''

i.e. You may abuse it to do type conversion or validation at runtime.

20

Reference

21

Thank you

Rick Mak

Oursky

CC81327D

Use the left and right arrow keys or click the left and right edges of the page to navigate between slides.
(Press 'H' or navigate to hide this message.)