From c18004611b0f1070110441cb9c68d95c06498aa2 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Thu, 10 Nov 2016 16:17:20 +0100 Subject: [PATCH 1/2] Update docs on runtime use of generic types --- docs/source/generics.rst | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/docs/source/generics.rst b/docs/source/generics.rst index d742ff425e1ff..4b9bdff87bc10 100644 --- a/docs/source/generics.rst +++ b/docs/source/generics.rst @@ -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 @@ -57,24 +57,31 @@ 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) - +__main__.Stack >>> print(Stack[int]) - +__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] - +typing.List[int] +>>> List[int].__bases__ +(, 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. From 429e6b399cb47fdd9e169ee765c81dfd491131bb Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Thu, 10 Nov 2016 16:25:33 +0100 Subject: [PATCH 2/2] Add one more example --- docs/source/generics.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/source/generics.rst b/docs/source/generics.rst index 4b9bdff87bc10..346ea0f17006c 100644 --- a/docs/source/generics.rst +++ b/docs/source/generics.rst @@ -53,6 +53,19 @@ 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 ***********************