PEP 484: Clarify type erasure and instantiation of concrete collections (#193)
Fixes python/typing#367
This commit is contained in:
parent
c9cf921546
commit
ccae12b0ba
47
pep-0484.txt
47
pep-0484.txt
|
@ -544,9 +544,8 @@ However, there are some special cases in the static typechecking context:
|
|||
Instantiating generic classes and type erasure
|
||||
----------------------------------------------
|
||||
|
||||
Generic types like ``List`` or ``Sequence`` cannot be instantiated.
|
||||
However, user-defined classes derived from them can be instantiated.
|
||||
Suppose we write a ``Node`` class inheriting from ``Generic[T]``::
|
||||
User-defined generic classes can be instantiated. Suppose we write
|
||||
a ``Node`` class inheriting from ``Generic[T]``::
|
||||
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
|
@ -583,27 +582,39 @@ the variable, e.g.::
|
|||
a = Node() # type: Node[int]
|
||||
b = Node() # type: Node[str]
|
||||
|
||||
You can also create a type alias (see above) for a specific concrete
|
||||
type and instantiate it, e.g.::
|
||||
Alternatively, you can instantiate a specific concrete type, e.g.::
|
||||
|
||||
# (continued from previous example)
|
||||
IntNode = Node[int]
|
||||
StrNode = Node[str]
|
||||
p = IntNode() # Inferred type is Node[str]
|
||||
q = StrNode() # Inferred type is Node[int]
|
||||
r = IntNode('') # Error
|
||||
s = StrNode(0) # Error
|
||||
p = Node[int]()
|
||||
q = Node[str]()
|
||||
r = Node[int]('') # Error
|
||||
s = Node[str](0) # Error
|
||||
|
||||
Note that the runtime type (class) of p and q is still just ``Node``
|
||||
-- ``IntNode`` and ``StrNode`` are distinguishable class objects, but
|
||||
the type (class) of the objects created by instantiating them doesn't
|
||||
record the distinction. This behavior is called "type erasure"; it is
|
||||
Note that the runtime type (class) of ``p`` and ``q`` is still just ``Node``
|
||||
-- ``Node[int]`` and ``Node[str]`` are distinguishable class objects, but
|
||||
the runtime class of the objects created by instantiating them doesn't
|
||||
record the distinction. This behavior is called "type erasure"; it is
|
||||
common practice in languages with generics (e.g. Java, TypeScript).
|
||||
|
||||
Generic versions of abstract collections like ``Mapping`` or ``Sequence``
|
||||
and generic versions of built-in classes -- ``List``, ``Dict``, ``Set``,
|
||||
and ``FrozenSet`` -- cannot be instantiated. However, concrete user-defined
|
||||
subclasses thereof and generic versions of concrete collections can be
|
||||
instantiated::
|
||||
|
||||
data = DefaultDict[int, bytes]()
|
||||
|
||||
Note that one should not confuse static types and runtime classes.
|
||||
The type is still erased in this case and the above expression is
|
||||
just a shorthand for::
|
||||
|
||||
data = collections.defaultdict() # type: DefaultDict[int, bytes]
|
||||
|
||||
It is not recommended to use the subscripted class (e.g. ``Node[int]``)
|
||||
directly in an expression -- using a type alias instead is preferred.
|
||||
(First, creating the subscripted class, e.g. ``Node[int]``, has a runtime
|
||||
cost. Second, using a type alias is more readable.)
|
||||
directly in an expression -- using a type alias (e.g. ``IntNode = Node[int]``)
|
||||
instead is preferred. (First, creating the subscripted class,
|
||||
e.g. ``Node[int]``, has a runtime cost. Second, using a type alias
|
||||
is more readable.)
|
||||
|
||||
|
||||
Arbitrary generic types as base classes
|
||||
|
|
Loading…
Reference in New Issue