[Python-ideas] Runtime types vs static types

Koos Zevenhoven k7hoven at gmail.com
Sun Jun 25 13:11:56 EDT 2017


On Sun, Jun 25, 2017 at 7:13 PM, Lucas Wiman <lucas.wiman at gmail.com> wrote:
[...]

> >>> from typing import *
> >>> isinstance(0, Union[int, float])
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "/Users/lucaswiman/.pyenv/versions/3.6/lib/python3.6/typing.py",
> line 767, in __instancecheck__
>     raise TypeError("Unions cannot be used with isinstance().")
> TypeError: Unions cannot be used with isinstance().
>
> I think the natural reaction of naive users of the library is "That's
> annoying. Why? What is this library good for?", not "Ah, I've sagely
> learned a valuable lesson about the subtle-and-important-though-unmentioned
> distinction between types and classes!" The restriction against runtime
> type checking makes `typing` pretty much *only* useful when used with the
> external library `mypy` (or when writing a library with the same purpose as
> `mypy`), which is a pretty unusual situation for a standard library module.
>
> Mark Shannon's example also specifically does not apply to the types I'm
> thinking of for the reasons I mentioned:
>
>> For example,
>> List[int] and List[str] and mutually incompatible types, yet
>> isinstance([], List[int]) and isinstance([], List[str))
>> both return true.
>>
>> There is no corresponding objection for `Union`; I can't think of any*
> inconsistencies or runtime type changes that would result from defining
> `_Union.__instancecheck__` as `any(isinstance(obj, t) for t in
> self.__args__`.
>

​One thing is that, as long as not all types support isinstance, then also
isinstance(obj, Union[x, y, z])​ will fail for some x, y, z. From some
perspective, that may not be an issue, but on the other hand, it may invite
people to think that all types do support isinstance.

For `Tuple`, it's true that `()` would be an instance of `Tuple[X, ...]`
> for all types X. However, the objection for the `List` case (IIUC;
> extrapolating slightly) is that the type of the object could change
> depending on what's added to it. That's not true for tuples since they're
> immutable, so it's not *inconsistent* to say that `()` is an instance of
> `Tuple[int, ...]` and `Tuple[str, ...]`, it's just applying a sensible
> definition to the base case of an empty tuple.
>
>
​Yes, but then `isinstance(tuple(range(1000000)), Tuple[int, ...])` would
be a difficult case.

I think it all comes down to how much isinstance should pretend to be able
to do with *types* (as opposed to only classes). Maybe isinstance is not
the future of runtime type checking ;). Or should isinstance have a third
return value like `Possibly`?

-- Koos
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170625/afedfa05/attachment.html>


More information about the Python-ideas mailing list