15

I am reading the typing module code and also looking into mypy to understand how it does type checking. Unfortunately for me, mypy builds a very smart tree with typed expressions that I still don't understand, and it's all based on static analysis.

I would like to implement a type check system that is dynamic (no static analysis) in Python. Assuming the function that performs type checks is called check_type, I want to accomplish the following:

>>> import typing >>> >>> check_type(1, int) True >>> check_type(1, float) False >>> check_type([1], typing.List[int]) True >>> check_type([1], typing.List[float]) False >>> check_type([1], typing.List[typing.Any]) True >>> check_type((1,), typing.Tuple[int]) True 

I thought about recreating the object type from its value, such as:

>>> get_type([1]) typing.List<~T>[int] 

But this doesn't work with issubclass:

>>> issubclass(typing.List[int], typing.List[typing.Any]) False 

I don't see a simple way to check types in Python without assuming a lot of things about the internals of the typing stdlib module (e.g., accessing __args__ or __tuple_params__).

How can I properly implement a check_type function that work for the cases previously listed? I am using Python 2.7.

12
  • Isn't this just isinstance? Commented Jun 22, 2016 at 16:39
  • 1
    No, @user2357112. isinstance doesn't check the type completely. For example: isinstance(['string'], typing.List[int]) is True when that's not exactly what I am looking for. Commented Jun 22, 2016 at 16:42
  • 1
    @freakish: Check out mypy, a static type analysis tool for Python and one of the big drivers behind type hints. Commented Jun 22, 2016 at 16:48
  • 2
    Not really an answer but the pythonic way to check types is to use a try/except statement and treat the value you want to test as the value you expect and if a TypeError exception is raised do something else or just pass Commented Jun 22, 2016 at 16:49
  • 2
    @freakish: PEP-484 (accepted). Although it doesn't quite apply to Python 2.7. Commented Jun 22, 2016 at 17:00

1 Answer 1

4

You can easily get the very limited functionality that works correctly for the simple examples provided in your question:

import mypy.api def check_type(value, typ): program_text = 'from typing import *; v: {} = {}'.format(typ, repr(value)) normal_report, error_report, exit_code = mypy.api.run(['-c', program_text]) return exit_code == 0 int_ = 1 str_ = 'a' list_str_ = ['a'] list_int_ = [1] tuple_int_ = (1,) assert check_type(int_, 'int') assert not check_type(str_, 'int') assert check_type(list_int_, 'List[int]') assert not check_type(list_str_, 'List[int]') assert check_type(list_int_, 'List[Any]') assert check_type(tuple_int_, 'Tuple[int]') 

You can even do some more advanced stuff (for example, refer to the types that correspond to classes you defined in your program) by extending this code a bit, so that mypy gets to parse your entire source code as opposed to just the current line.

Alternatively, you might want to look at enforce or typeguard.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.