From 6b703135a0ca9f62bf2a17a0b0d07d93386bef9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Wed, 19 Feb 2020 00:35:45 +0100 Subject: [PATCH] [pep-585] Disallow isinstance([1, 2], list[str]) --- pep-0585.rst | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/pep-0585.rst b/pep-0585.rst index 4a30235e08c..0820abc8721 100644 --- a/pep-0585.rst +++ b/pep-0585.rst @@ -165,8 +165,6 @@ parametrized collections, like:: >>> l = list[str]() [] - >>> isinstance([1, 2, 3], list[str]) - True >>> list is list[str] False >>> list == list[str] @@ -175,6 +173,12 @@ parametrized collections, like:: True >>> list[str] == list[int] False + >>> isinstance([1, 2, 3], list[str]) + TypeError: isinstance() arg 2 cannot be a parametrized generic + >>> issubclass(list, list[str]) + TypeError: issubclass() arg 2 cannot be a parametrized generic + >>> isinstance(list[str], types.GenericAlias) + True Objects created with bare types and parametrized types are exactly the same. The generic parameters are not preserved in instances created @@ -301,6 +305,31 @@ including parallels of collections in the standard library. Moreover, Python allows for instantiation of lists using ``list()`` and some builtin collections don't provide special syntax for instantiation. +Making ``isinstance(obj, list[str])`` perform a check ignoring generics +----------------------------------------------------------------------- + +An earlier version of this PEP suggested treating parametrized generics +like ``list[str]`` as equivalent to their non-parametrized variants +like ``list`` for purposes of ``isinstance()`` and ``issubclass()``. +This would be symmetrical to how ``list[str]()`` creates a regular list. + +This design was rejected because ``isinstance()`` and ``issubclass()`` +checks with parametrized generics would read like element-by-element +runtime type checks. The result of those checks would be surprising, +for example:: + + >>> isinstance([1, 2, 3], list[str]) + True + +Note the object doesn't match the provided generic type but +``isinstance()`` still returns ``True`` because it only checks whether +the object is a list. + +If a library is faced with a parametrized generic and would like to +perform an ``isinstance()`` check using the base type, that type can +be retrieved using the ``__origin__`` attribute on the parametrized +generic. + Making ``isinstance(obj, list[str])`` perform a runtime type check ------------------------------------------------------------------