[pep-585] Address GvR's review comments

This commit is contained in:
Łukasz Langa 2019-09-20 17:46:18 +02:00
parent 4aa98027b3
commit bd03d819a1
No known key found for this signature in database
GPG Key ID: B26995E310250568
1 changed files with 32 additions and 26 deletions

View File

@ -34,26 +34,26 @@ and easier for teachers to teach Python.
Terminology Terminology
=========== ===========
Generic (n.) a type that can be parametrized, typically a container. Generic (n.) -- a type that can be parametrized, typically a container.
Also known as a *parametric type* or a *generic type*. For example: Also known as a *parametric type* or a *generic type*. For example:
``dict``. ``dict``.
Parametrized generic a specific instance of a generic with the Parametrized generic -- a specific instance of a generic with the
expected types for container elements provided. For example: expected types for container elements provided. Also known as
``dict[str, int]``. a *parametrized type*. For example: ``dict[str, int]``.
Backwards compatibility Backwards compatibility
======================= =======================
The newly described functionality requires Python 3.9. For use cases
restricted to type annotations, Python files with the "annotations"
future-import (available since Python 3.7) can use generics in
combination with standard collections, including builtins.
Tooling, including type checkers and linters, will have to be adapted to Tooling, including type checkers and linters, will have to be adapted to
recognize such generics usage as valid. recognize standard collections as generics.
On the source level, the newly described functionality requires
Python 3.9. For use cases restricted to type annotations, Python files
with the "annotations" future-import (available since Python 3.7) can
parametrize standard collections, including builtins. To reiterate,
that depends on the external tools understanding that this is valid.
Implementation Implementation
============== ==============
@ -67,7 +67,9 @@ collections directly. Example::
def find(haystack: dict[str, list[int]]) -> int: def find(haystack: dict[str, list[int]]) -> int:
... ...
Certain features of typing like type aliases or casting require putting Usefulness of this syntax before PEP 585 is limited as external tooling
like Mypy does not recognize standard collections as generic. Moreover,
certain features of typing like type aliases or casting require putting
types outside of annotations, in runtime context. While these are types outside of annotations, in runtime context. While these are
relatively less common than type annotations, it's important to allow relatively less common than type annotations, it's important to allow
using the same type syntax in all contexts. This is why starting with using the same type syntax in all contexts. This is why starting with
@ -111,9 +113,16 @@ Python 3.9, the following collections become generic using
* ``contextlib.AbstractContextManager`` # typing.ContextManager * ``contextlib.AbstractContextManager`` # typing.ContextManager
* ``contextlib.AbstractAsyncContextManager`` # typing.AsyncContextManager * ``contextlib.AbstractAsyncContextManager`` # typing.AsyncContextManager
Importing those from ``typing`` is deprecated. Type checkers may warn Importing those from ``typing`` is deprecated. Due to PEP 563 and the
intention to minimize the runtime impact of typing, this deprecation
will not generate DeprecationWarnings. Instead, type checkers may warn
about such deprecated usage when the target version of the checked about such deprecated usage when the target version of the checked
program is signalled to be Python 3.9 or newer. program is signalled to be Python 3.9 or newer. It's recommended to
allow for those warnings to be silenced on a project-wide basis.
The deprecated functionality will be removed from the ``typing`` module
in the first Python version released 5 years after the release of
Python 3.9.0.
Parameters to generics are available at runtime Parameters to generics are available at runtime
@ -229,10 +238,9 @@ used for API generation or runtime type checking. Such usage is already
present in the wild. present in the wild.
Additionally, implementing subscripts as identity functions would make Additionally, implementing subscripts as identity functions would make
Python less friendly to beginners. Let's demonstrate this with an Python less friendly to beginners. Say, if a user is mistakenly passing
example. If a user is passing a list type instead of a list object to a list type instead of a list object to a function, and that function is
a function, and that function is using indexing, the code would no indexing the received object, the code would no longer raise an error.
longer raise an error.
Today:: Today::
@ -247,19 +255,18 @@ With ``__class_getitem__`` as an identity function::
list list
The indexing being successful here would likely end up raising an The indexing being successful here would likely end up raising an
exception at a distance and with a confusing error message to the user. exception at a distance, confusing the user.
Disallowing instantiation of parametrized types Disallowing instantiation of parametrized types
----------------------------------------------- -----------------------------------------------
Given that the proxy type which preserves ``__origin__`` and Given that the proxy type which preserves ``__origin__`` and
``__parameters__`` is mostly useful for static analysis or runtime ``__parameters__`` is mostly useful for runtime introspection purposes,
introspection purposes, we might have disallowed instantiation of we might have disallowed instantiation of parametrized types.
parametrized types.
In fact, this is what the ``typing`` module does today for types which In fact, forbidding instantiation of parametrized types is what the
parallel builtin collections (instantiation of other parametrized types ``typing`` module does today for types which parallel builtin
is allowed). collections (instantiation of other parametrized types is allowed).
The original reason for this decision was to discourage spurious The original reason for this decision was to discourage spurious
parametrization which made object creation up to two orders of magnitude parametrization which made object creation up to two orders of magnitude
@ -279,8 +286,7 @@ This functionality requires iterating over the collection which is
a destructive operation in some of them. This functionality would have a destructive operation in some of them. This functionality would have
been useful, however implementing the type checker within Python that been useful, however implementing the type checker within Python that
would deal with complex types, nested type checking, type variables, would deal with complex types, nested type checking, type variables,
string forward references, and so on is out of scope for this PEP. This string forward references, and so on is out of scope for this PEP.
can be revised in the future.
Note on the initial draft Note on the initial draft