16

does python 3.5 provide functions that allow to test whether a given argument would fit the type hints given in the function declaration?

if i have e.g. this function:

def f(name: List[str]):
    pass

is there a python method that can check whether

name = ['a', 'b']
name = [0, 1]
name = []
name = None
...

fit the type hints?

i know that 'no type checking happens at runtime' but can i still check the validity of these arguments by hand in python?

or if python does not provide that functionality itself: what is the tool i'd need to use?

hiro protagonist
  • 44,693
  • 14
  • 86
  • 111
  • 1
    *"does python 3.5 provide functions that allow to test whether a given argument would fit the type hints given in the function declaration?"* - no (but it's [getting closer](https://www.python.org/dev/peps/pep-0484/)). *"what is the tool i'd need to use?"* - recommendations are off-topic (but see MyPy, [contracts](http://andreacensi.github.io/contracts/), etc.) – jonrsharpe Sep 29 '15 at 12:58

2 Answers2

19

Python itself doesn't provide such functions, you can read more about it here:


I wrote a decorator for that. This is the code of my decorator:

from typing import get_type_hints

def strict_types(function):
    def type_checker(*args, **kwargs):
        hints = get_type_hints(function)

        all_args = kwargs.copy()
        all_args.update(dict(zip(function.__code__.co_varnames, args)))

        for argument, argument_type in ((i, type(j)) for i, j in all_args.items()):
            if argument in hints:
                if not issubclass(argument_type, hints[argument]):
                    raise TypeError('Type of {} is {} and not {}'.format(argument, argument_type, hints[argument]))

        result = function(*args, **kwargs)

        if 'return' in hints:
            if type(result) != hints['return']:
                raise TypeError('Type of result is {} and not {}'.format(type(result), hints['return']))

        return result

    return type_checker

You can use it like that:

@strict_types
def repeat_str(mystr: str, times: int):
    return mystr * times

Though it's not very pythonic to restrict your function to accept only one type. Though you can use abc (abstract base classes) like number (or custom abc) as type-hints and restrict your functions to accept not only one type, but whatever combination of types you want.


Added a github repo for it, if anybody wants to use it.

Community
  • 1
  • 1
Ilya Peterov
  • 1,975
  • 1
  • 16
  • 33
  • this looks nice. `f.__code__` should be `function.__code__`; the arguments of the first `TypeError` should also be adapted. i tried your `repeat_str` function and got an (unexpected) error message: `TypeError: Type of mystr is and not `. but then maybe i introduced a bug into your code... – hiro protagonist Sep 29 '15 at 14:01
  • 1
    @hiroprotagonist, I'm sorry, I gave you the wrong, not debugged code. I edited my answer, now it probably works as it should. – Ilya Peterov Sep 29 '15 at 23:36
  • 2
    hi, this is a really good answer actually. But maybe `hints = get_type_hints(function)` could be put outside the decorator function: there's no need to calculate them every time the function is executed :) – Giuppox Mar 19 '21 at 09:08
9

This is an old question, but there is a tool I've written for doing run time type checking based on type hints: https://pypi.org/project/typeguard/

Alex Grönholm
  • 5,563
  • 29
  • 32
  • `typeguard` looks really nice. Handles `List`, `Union`, `Typevar` etc. which the proof-of-concept accepted answer won't do. It would be interesting to see what the performance hit is from running it though, although I guess this could be mitigated by e.g. running only in debug. – markmuetz Jul 01 '18 at 11:10