29

In Python 3.5, type annotations were added (see here).

Is there a way of defining recursive type annotations, such as for a tree-like structure?

class Employee(object):
    def __init__(self, name: str, reports: List[Employee]):
       self.name = name
       self.reports = reports

In the above, it doesn't seem as though the annotation List[Employee] works. Running the code results in this error:

NameError: name 'Employee' is not defined

Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
nimda
  • 700
  • 7
  • 9

1 Answers1

49

You can use Forward References as defined in PEP 484

A situation where this occurs commonly is the definition of a container class, where the class being defined occurs in the signature of some of the methods. For example, the following code (the start of a simple binary tree implementation) does not work:

class Tree:
    def __init__(self, left: Tree, right: Tree):
        self.left = left
        self.right = right

To address this, we write:

class Tree:
    def __init__(self, left: 'Tree', right: 'Tree'):
        self.left = left
        self.right = right

It is allowable to use string literals as part of a type hint, for example:

class Tree:
    ...
    def leaves(self) -> List['Tree']:
Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
  • 6
    Note that this will not be necessary since Python3.10, and can be optionally avoided with `from __future__ import annotations`, see the table at the bottom of https://docs.python.org/3.8/library/__future__.html – M. Volf Dec 31 '20 at 17:03
  • 2
    Note that Python 3.10's annotations change ended up causing problems but it was too late to take it back in 3.10, so there is discussion of changing it yet again. See for example [PEP-649](https://peps.python.org/pep-0649/). – mtraceur Jun 20 '22 at 19:56