GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing peps.python.org — PEP 585 – Type Hinting Generics In Standard Collections | peps.python.org
PEP 585 – Type Hinting Generics In Standard Collections
PEP 585 – Type Hinting Generics In Standard Collections
Important This PEP is a historical document. The up-to-date, canonical documentation can now be found at Generic Alias Type
and the documentation for × See PEP 1 for how to propose changes. AbstractStatic typing as defined by PEPs 484, 526, 544, 560, and 563 was built
incrementally on top of the existing Python runtime and constrained by
existing syntax and runtime behavior. This led to the existence of
a duplicated collection hierarchy in the This PEP proposes to enable support for the generics syntax in all
standard collections currently available in the Rationale and GoalsThis change removes the necessity for a parallel type hierarchy in the
TerminologyGeneric (n.) – a type that can be parameterized, typically a container.
Also known as a parametric type or a generic type. For example:
parameterized generic – a specific instance of a generic with the
expected types for container elements provided. Also known as
a parameterized type. For example: Backwards compatibilityTooling, including type checkers and linters, will have to be adapted to 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 parameterize standard collections, including builtins. To reiterate, that depends on the external tools understanding that this is valid. ImplementationStarting with Python 3.7, when from __future__ import annotations def find(haystack: dict[str, list[int]]) -> int: ... 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
Python 3.9, the following collections become generic using
Importing those from The deprecated functionality may eventually be removed from the Parameters to generics are available at runtimePreserving the generic type at runtime enables introspection of the type which can be used for API generation or runtime type checking. Such usage is already present in the wild. Just like with the >>> list[str] list[str] >>> tuple[int, ...] tuple[int, ...] >>> ChainMap[str, list[str]] collections.ChainMap[str, list[str]] This is implemented using a thin proxy type that forwards all method calls and attribute accesses to the bare origin type with the following exceptions:
This design means that it is possible to create instances of parameterized collections, like: >>> l = list[str]() [] >>> list is list[str] False >>> list == list[str] False >>> list[str] == list[str] True >>> list[str] == list[int] False >>> isinstance([1, 2, 3], list[str]) TypeError: isinstance() arg 2 cannot be a parameterized generic >>> issubclass(list, list[str]) TypeError: issubclass() arg 2 cannot be a parameterized generic >>> isinstance(list[str], types.GenericAlias) True Objects created with bare types and parameterized types are exactly the same. The generic parameters are not preserved in instances created with parameterized types, in other words generic types erase type parameters during object creation. One important consequence of this is that the interpreter does not attempt to type check operations on the collection created with a parameterized type. This provides symmetry between: l: list[str] = [] and: l = list[str]() For accessing the proxy type from Python code, it will be exported
from the Pickling or (shallow- or deep-) copying a Forward compatibilityFuture standard collections must implement the same behavior. Reference implementationA proof-of-concept or prototype implementation exists. Rejected alternativesDo nothingKeeping the status quo forces Python programmers to perform book-keeping
of imports from the The above problems also don’t exist in user-built generic classes which share runtime functionality and the ability to use them as generic type annotations. Making standard collections harder to use in type hinting from user classes hindered typing adoption and usability. Generics erasureIt would be easier to implement >>> list[str] <class 'list'> >>> tuple[int, ...] <class 'tuple'> >>> collections.ChainMap[str, list[str]] <class 'collections.ChainMap'> This is problematic as it breaks backwards compatibility: current
equivalents of those types in the >>> from typing import List, Tuple, ChainMap >>> List[str] typing.List[str] >>> Tuple[int, ...] typing.Tuple[int, ...] >>> ChainMap[str, List[str]] typing.ChainMap[str, typing.List[str]] As mentioned in the “Implementation” section, preserving the generic type at runtime enables runtime introspection of the type which can be 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. 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: >>> l = list >>> l[-1] TypeError: 'type' object is not subscriptable With >>> l = list >>> l[-1] list The indexing being successful here would likely end up raising an exception at a distance, confusing the user. Disallowing instantiation of parameterized typesGiven that the proxy type which preserves In fact, forbidding instantiation of parameterized types is what the
The original reason for this decision was to discourage spurious parameterization which made object creation up to two orders of magnitude slower compared to the special syntax available for those builtin collections. This rationale is not strong enough to allow the exceptional treatment
of builtins. All other parameterized types can be instantiated,
including parallels of collections in the standard library. Moreover,
Python allows for instantiation of lists using Making
|
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |