[Python-ideas] Runtime types vs static types

Koos Zevenhoven k7hoven at gmail.com
Thu Jun 29 09:30:21 EDT 2017

On Thu, Jun 29, 2017 at 12:40 PM, Ivan Levkivskyi <levkivskyi at gmail.com>

> Sorry, I was not able to completely digest the OP, but I think there are
> some points I need to clarify.
> 1. Distinction between runtime classes and static types is quite sane and
> a simple idea.
> A runtime class is something associated with an actual object,
> while static type is something associated with an AST node.

Here, ​I'm more concerned about *types* at runtime vs *types* for static
checking. Some of these may be normal classes, but those are not the
problematic ones.​

> Mixing them would be misleading, since they "live in parallel planes".
> Although it is true that there is a type that corresponds to every runtime
> class.

​It's not clear to me what you mean by mixing them. They are already partly
mixed, right? I think you are speaking from the static-checker point of
view, where there are only types, and runtime behavior is completely
separate (at least in some sense). This view works especially well when
types are in comments or stubs. But when the types are also present at
runtime, I don't think this view is completely realistic.

Some of the objects that represent types are regular classes, and some of
them may be only types (like Union[str, bytes] or Sequence[int]), but not
normal Python classes that you instantiate. Even if they represent types,
not classes, they exist at runtime, and there should at least *exist* a
well-defined answer to whether an object is in 'instance' of a given type.
(Not sure if 'instance' should be world used here)

Ignoring that *types* are also a runtime concept seems dangerous to me.

> 2. Currently isinstance(obj, List[int]) fails with TypeError, ditto for
> issubclass and
> for user defined generic classes:
> class C(Generic[T]):
>     ...
> isinstance(obj, C)  # works, returns only True or False
> isinstance(obj, C[int])  # TypeError
> issubclass(cls, C)  # works
> issubclass(cls, C[int])  # raisesTypeError
​I suppose that's the best that isinstance can do in these cases. But I'm
not sure if isinstance and issubclass should try to do as much as
reasonable, or if it they should just handle the normal classes, and let
some new function, say implements(), take care of the other *types*.
​Anyway, this whole concept of two 'parallel universes' is problematic,
because the universes overlap in at least two different ways.

​-- Koos​

3. User defined protocols will by default raise TypeError with isinstance(),
> but the user can opt-in (using @runtime decorator) for the same behavior
> as normal generics,
> this is how typing.Iterable currently works:
> class MyIter:
>     def __iter__(self):
>         return [42]
> isinstance(MyIter(), Iterable)  # True
> isinstance(MyIter(), Iterable[int])  # TypeError
> class A(Protocol[T]):
>     x: T
> isinstance(obj, A)  # TypeError
> @runtime
> class B(Protocol[T]):
>     y: T
> isinstance(obj, B)  # True or False depending on whether 'obj' has
> attribute 'y'
> isinstance(obj, B[int])  # Still TypeError
> --
> Ivan

+ Koos Zevenhoven + http://twitter.com/k7hoven +
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170629/04e0709f/attachment-0001.html>

More information about the Python-ideas mailing list