[Python-ideas] Runtime types vs static types

Lucas Wiman lucas.wiman at gmail.com
Sun Jun 25 13:47:46 EDT 2017


> ​Yes, but then `isinstance(tuple(range(1000000)), Tuple[int, ...])` would
be a difficult case.

Yes, many methods on million-element tuples are slow. :-)

Python usually chooses the more intuitive behavior over the faster behavior
when there is a choice. IIUC, the objections don't have anything to do with
speed.

- Lucas

On Sun, Jun 25, 2017 at 10:11 AM, Koos Zevenhoven <k7hoven at gmail.com> wrote:

> 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/c2a48390/attachment-0001.html>


More information about the Python-ideas mailing list