Self-reference of type annotations in Python
Question: I'm trying to figure out how self-reference of types work with [python3's type
annotations](https://docs.python.org/3/library/typing.html) \- the docs don't
specify anything regarding this.

As an example:

    
    
    from typing import TypeVar, Optional, Generic
    
    T = TypeVar('T')
    class Node(Generic[T]):
        left = None
        right = None
        value = None
    
        def __init__(
            self, value: Optional[T],
            left: Optional[Node[T]]=None,
            right: Optional[Node[T]]=None,
        ) -> None:
            self.value = value
            self.left = left
            self.right = right
    

This code generates the error:

    
    
    Traceback (most recent call last):
      File "node.py", line 4, in <module>
        class Node(Generic[T]):
      File "node.py", line 12, in Node
        right: Optional[Node[T]]=None,
    NameError: name 'Node' is not defined
    

This is using Python 3.5.1


Answer: [PEP 0484 - Type Hints - The problem of forward
declarations](https://www.python.org/dev/peps/pep-0484/#the-problem-of-
forward-declarations) addresses the issue:

> The problem with type hints is that annotations (per [PEP
> 3107](https://www.python.org/dev/peps/pep-3107/) , and similar to default
> values) are evaluated at the time a function is defined, and thus any names
> used in an annotation must be already defined when the function is being
> defined. A common scenario is a class definition whose methods need to
> reference the class itself in their annotations. (More general, it can also
> occur with mutually recursive classes.) This is natural for container types,
> for example:
>
> ...
>
> As written this will not work, because of the peculiarity in Python that
> class names become defined once the entire body of the class has been
> executed. **Our solution, which isn't particularly elegant, but gets the job
> done, is to allow using string literals in annotations.** Most of the time
> you won't have to use this though -- most uses of type hints are expected to
> reference builtin types or types defined in other modules.

from typing import TypeVar, Optional, Generic

    
    
    T = TypeVar('T')
    class Node(Generic[T]):
        left = None
        right = None
        value = None
    
        def __init__(
            self,
            value: Optional[T],
            left: Optional['Node[T]']=None,
            right: Optional['Node[T]']=None,
        ) -> None:
            self.value = value
            self.left = left
            self.right = right
    

* * *
    
    
    >>> import typing
    >>> typing.get_type_hints(Node.__init__)
    {'return': None,
     'value': typing.Union[~T, NoneType],
     'left': typing.Union[__main__.Node[~T], NoneType],
     'right': typing.Union[__main__.Node[~T], NoneType]}
    

