Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 29 additions & 9 deletions docs/source/generics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Using ``Stack`` is similar to built-in container types:
.. code-block:: python

# Construct an empty Stack[int] instance
stack = Stack() # type: Stack[int]
stack = Stack[int]()
stack.push(2)
stack.pop()
stack.push('x') # Type error
Expand All @@ -53,28 +53,48 @@ Type inference works for user-defined generic types as well:

process(Stack()) # Argument has inferred type Stack[int]

Construction of instances of generic types is also type checked:

.. code-block:: python

class Box(Generic[T]):
def __init__(self, content: T) -> None:
self.content = content

Box(1) # OK, inferred type is Box[int]
Box[int](1) # Also OK
s = 'some string'
Box[int](s) # Type error

Generic class internals
***********************

You may wonder what happens at runtime when you index
``Stack``. Actually, indexing ``Stack`` just returns ``Stack``:
``Stack``. Actually, indexing ``Stack`` returns essentially a copy
of ``Stack`` that returns instances of the original class on
instantiation:

>>> print(Stack)
<class '__main__.Stack'>
__main__.Stack
>>> print(Stack[int])
<class '__main__.Stack'>
__main__.Stack[int]
>>> print(Stack[int]().__class__)
__main__.Stack

Note that built-in types ``list``, ``dict`` and so on do not support
indexing in Python. This is why we have the aliases ``List``, ``Dict``
and so on in the ``typing`` module. Indexing these aliases just gives
you the target class in Python, similar to ``Stack``:
and so on in the ``typing`` module. Indexing these aliases gives
you a class that directly inherits from the target class in Python:

>>> from typing import List
>>> List[int]
<class 'list'>
typing.List[int]
>>> List[int].__bases__
(<class 'list'>, typing.MutableSequence)

The above examples illustrate that type variables are erased at
runtime. Generic ``Stack`` or ``list`` instances are just ordinary
Generic types could be instantiated or subclassed as usual classes,
but the above examples illustrate that type variables are erased at
runtime. Generic ``Stack`` instances are just ordinary
Python objects, and they have no extra runtime overhead or magic due
to being generic, other than a metaclass that overloads the indexing
operator.
Expand Down