I was excited to learn about SupportsInt, SupportsFloat, and SupportsComplex protocols decorated with @runtime_checkable because I thought they bridged the gap between ABCs and typing protocol classes, allowing consistent type checks by static tools and at runtime.
However, I am unable to see how to use those classes in practice.
For example, SupportsComplex: I understand at runtime the @runtime_checkable decorator merely checks whether __complex__ exists in the type, but that is not a good predictor of how to use a numeric value.
Types that actually can be converted to complex fail the insinstance check with SupportsComplex. That's the case of built-in int and float, as well as NumPy integer and float types like float16 and uint8.
On the other hand, SupportsInt suggests that I can convert a complex to int, but in fact the int and float types implement __complex__ only to provide a better error message, according to Guido van Rossum in an earlier thread here.
isinstance(1+0j, SupportsInt) True int(1+0j) Traceback (most recent call last): ... TypeError: can't convert complex to int
The issue with SupportsInt also happens with SupportsFloat.
In addition, the way Mypy interprets these protocol classes is not the same as what we can see at runtime.
Given the above, what are recommended use cases for the runtime checkable SupportsInt, SupportsFloat, and SupportsComplex?
-- Luciano Ramalho | Author of Fluent Python (O'Reilly, 2015) | http://shop.oreilly.com/product/0636920032519.do | Technical Principal at ThoughtWorks | Twitter: @ramalhoorg