Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does isinstance([1, 2, 3], List[str]) evaluate to true?

I was playing around a bit with the new type hinting / typing module with python3.5 trying to find a way to confirm if the hinted type is equal to the actual type of the variable and came across something that rather surprised me.

>>> from typing import List
>>> someList = [1, 2, 3]
>>> isinstance(someList, List[str])
True

Continuing my search for finding a way to compare a variable to it's hinted type I've also tried this:

>>> anotherList = ["foo", "bar"]
>>> type(anotherList) is List[str]
False

Would anyone be able to explain why exactly the former evaluates to True?

And continuing onwards, is there a sound way to check if a variable's type is equal to a type coming from the typing module?

like image 564
McMuffinton Avatar asked Sep 25 '15 19:09

McMuffinton


People also ask

What is the purpose of Isinstance () function?

The isinstance() function returns True if the specified object is of the specified type, otherwise False . If the type parameter is a tuple, this function will return True if the object is one of the types in the tuple.

Why is it better to use Isinstance?

isinstance is usually the preferred way to compare types. It's not only faster but also considers inheritance, which is often the desired behavior. In Python, you usually want to check if a given object behaves like a string or a list, not necessarily if it's exactly a string.

Is Isinstance the best way to check types?

Generally speaking isinstance is a 'more' elegant way of checking if an object is of a certain "type" (since you are aware of the Inheritance chain). On the other hand, if you are not aware of the inheritance chain and you need to be pick, go for type(x) == ...

What is the difference between the type () and Isinstance () in Python?

Difference Between type() and isinstance() in Python If the value and type given matches it will return true otherwise false. The return value is a Boolean i.e true or false. In case of type the subclass check gives back false. isinstance() gives a truthy value when checked with a subclass.


1 Answers

isinstance does not do real PEP 484 type checking. The documentation notes this in passing:

In general, isinstance() and issubclass() should not be used with types.

The typing module, as well as the collections.abc and abc modules it’s based on, use extensive __instancecheck__ and __subclasscheck__ magic to make isinstance and issubclass behave reasonably. But they’re not doing enough to support your case. Nor is it their goal to support it.

is there a sound way to check if a variable's type is equal to a type coming from the typing module?

You’re not looking for type equality. As you have noted yourself, the type of [1, 2, 3] is list, which is not equal to List[str], nor to List[int]. You’re looking for type checking, which is much more complicated.

Consider this:

def my_function():
    # ... 1000 lines of very complicated code ...

print(isinstance(my_function, Callable[[], int]))

What would you expect this program to print? You can’t expect isinstance to dig into my_function at runtime and infer that it always returns int. This is not feasible in Python. You need either a “compile” time type checker that has access to the structure of my_function, or explicit type annotations, or—most likely—both.

like image 112
Vasiliy Faronov Avatar answered Oct 31 '22 09:10

Vasiliy Faronov