from __future__ import annotations from typing import Any, Optional class Tree: """A recursive tree data structure. Representation Invariants: - self._root is not None or self._subtrees == [] """ # Private Instance Attributes: # - _root: # The item stored at this tree's root, or None if the tree is empty. # - _subtrees: # The list of subtrees of this tree. This attribute is empty when # self._root is None (representing an empty tree). However, this attribute # may be empty when self._root is not None, which represents a tree consisting # of just one item. _root: Optional[Any] _subtrees: list[Tree] def __init__(self, root: Optional[Any], subtrees: list[Tree]) -> None: """Initialize a new Tree with the given root value and subtrees. If root is None, the tree is empty. Preconditions: - root is not none or subtrees == [] """ self._root = root self._subtrees = subtrees def is_empty(self) -> bool: """Return whether this tree is empty. """ return self._root is None def __len__(self): if self.is_empty(): # tree is empty return 0 elif self._subtrees == []: # tree is a single item return 1 else: # tree has at least one subtree return 1 + sum(subtree.__len__() for subtree in self._subtrees)