[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
===========
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:
``dict``.
Parametrized generic a specific instance of a generic with the
expected types for container elements provided. For example:
``dict[str, int]``.
Parametrized generic -- a specific instance of a generic with the
expected types for container elements provided. Also known as
a *parametrized type*. For example: ``dict[str, int]``.
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
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
==============
@ -67,7 +67,9 @@ collections directly. Example::
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
relatively less common than type annotations, it's important to allow
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.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
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
@ -229,10 +238,9 @@ used for API generation or runtime type checking. Such usage is already
present in the wild.
Additionally, implementing subscripts as identity functions would make
Python less friendly to beginners. Let's demonstrate this with an
example. If a user is passing a list type instead of a list object to
a function, and that function is using indexing, the code would no
longer raise an error.
Python less friendly to beginners. Say, if a user is mistakenly passing
a list type instead of a list object to a function, and that function is
indexing the received object, the code would no longer raise an error.
Today::
@ -247,19 +255,18 @@ With ``__class_getitem__`` as an identity function::
list
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
-----------------------------------------------
Given that the proxy type which preserves ``__origin__`` and
``__parameters__`` is mostly useful for static analysis or runtime
introspection purposes, we might have disallowed instantiation of
parametrized types.
``__parameters__`` is mostly useful for runtime introspection purposes,
we might have disallowed instantiation of parametrized types.
In fact, this is what the ``typing`` module does today for types which
parallel builtin collections (instantiation of other parametrized types
is allowed).
In fact, forbidding instantiation of parametrized types is what the
``typing`` module does today for types which parallel builtin
collections (instantiation of other parametrized types is allowed).
The original reason for this decision was to discourage spurious
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
been useful, however implementing the type checker within Python that
would deal with complex types, nested type checking, type variables,
string forward references, and so on is out of scope for this PEP. This
can be revised in the future.
string forward references, and so on is out of scope for this PEP.
Note on the initial draft