The new typing
module contains several objects with names like "SupportsInt" (-Float, -Bytes, etc.). The name, and the descriptions on the documentation page for the module, might be read to suggest that you can test whether an object is of a type that "supports __int__()
". But if you try to use isinstance()
, it gives a response that makes it clear that that isn't something you are meant to do:
>>> isinstance(5, typing.SupportsInt)
(Traceback omitted)
TypeError: Protocols cannot be used with isinstance().
On the other hand, you can use issubclass()
:
>>> issubclass((5).__class__, typing.SupportsInt)
True
>>> issubclass(type(5), typing.SupportsInt)
True
What is a "protocol" in this context? Why does it disallow the use of isinstance()
in this way?
Definition and Usage 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.
The isinstance() function is faster than the type function. We can compare both their performance by using the timeit library. As you can see, the isinstance() function is 30 times faster than type() function.
This is all of the reasoning given in PEP 484
, the PEP for the typing
module:
Because typing.Callable does double-duty as a replacement for collections.abc.Callable , isinstance(x, typing.Callable) is implemented by deferring to `isinstance(x, collections.abc.Callable) . However, isinstance(x, typing.Callable[...]) is not supported.
A protocol is also known as a magic method
. These are most of the python protocols (full list here):
>>> dir(object)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__',
'__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__']
I have not found any clear reason for why typing
does not support isinstance
. The reason that issubclass
works is that isinstance
uses the __class_
protocol which is not allowed in typing
, while issubclass
uses the __subclasshook__
protocol which is allowed. I believe the reason is that the functionality was already coded in collections.abc.Callable
and they did not want to recode it in the typing
module.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With