diff --git a/pep-0585.rst b/pep-0585.rst index c3f16f139..6fee22365 100644 --- a/pep-0585.rst +++ b/pep-0585.rst @@ -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