Skip to content

PEP 585: Disallow isinstance([1, 2], list[str]) #1311

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 19, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions pep-0585.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand Down Expand Up @@ -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
------------------------------------------------------------------

Expand Down