Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python >=3.5: Checking type annotation at runtime

Does the typing module (or any other module) exhibit an API to typecheck a variable at runtime, similar to isinstance() but understanding the type classes defined in typing?

I'd like to be to run something akin to:

from typing import List assert isinstance([1, 'bob'], List[int]), 'Wrong type' 
like image 480
Bertrand Caron Avatar asked Apr 27 '17 00:04

Bertrand Caron


People also ask

Is Python type checked at runtime?

Python types do not provide runtime type-checking.

How do you check typing in Python?

If you need to check the type of an object, it is recommended to use the Python isinstance() function instead. It's because isinstance() function also checks if the given object is an instance of the subclass.

Is type checking good in Python?

Type hints work best in modern Pythons. Annotations were introduced in Python 3.0, and it's possible to use type comments in Python 2.7. Still, improvements like variable annotations and postponed evaluation of type hints mean that you'll have a better experience doing type checks using Python 3.6 or even Python 3.7.

What is union type in Python?

Union type; Union[X, Y] is equivalent to X | Y and means either X or Y. To define a union, use e.g. Union[int, str] or the shorthand int | str . Using that shorthand is recommended.


2 Answers

I was looking for something similar and found the library typeguard. This can automatically do runtime type checks wherever you want. Checking types directly as in the question is also supported. From the docs,

from typeguard import check_type  # Raises TypeError if there's a problem check_type('variablename', [1234], List[int]) 
like image 84
aravindsagar Avatar answered Sep 19 '22 11:09

aravindsagar


There is no such function in the typing module, and most likely there won't ever be.

Checking whether an object is an instance of a class - which only means "this object was created by the class' constructor" - is a simple matter of testing some tagging.

However, checking whether an object is an "instance" of a type is not necessarily decidable:

assert isinstance(foo, Callable[[int], str]), 'Wrong type' 

Although it is easy to inspect the typing annotations of foo (assuming it's not a lambda), checking whether it complies to them is generally undecidable, by Rice's theorem.

Even with simpler types, such as List[int] the test will easily become far too inefficient to be used for anything but the smallest toy examples.

xs = set(range(10000)) xs.add("a") xs.pop() assert isinstance(xs, Set[int]), 'Wrong type' 

The trick that allows type checker to perform this operation in a relatively efficient way, is to be conservative: the type checker tries to prove that foo always return int. If it fails, it rejects the program, even though the program may be valid, i.e. this function is likely to be rejected, although it is perfectly safe:

def foo() -> int:     if "a".startswith("a"):         return 1     return "x" 
like image 45
Elazar Avatar answered Sep 20 '22 11:09

Elazar