return a small binary tree with 3 nodes binarytree binarytree smalltree lenbinarytree 3 listbinarytree 1 2 3 return a medium binary tree with 3 nodes binarytree binarytree mediumtree lenbinarytree 7 listbinarytree 1 2 3 4 5 6 7 returns the depth of the tree binarytreenode1 depth 1 binarytree smalltree depth 2 binarytree mediumtree depth 4 returns true if the tree is full binarytreenode1 isfull true binarytree smalltree isfull true binarytree mediumtree isfull false return a small binary tree with 3 nodes binary_tree binarytree small_tree len binary_tree 3 list binary_tree 1 2 3 return a medium binary tree with 3 nodes binary_tree binarytree medium_tree len binary_tree 7 list binary_tree 1 2 3 4 5 6 7 returns the depth of the tree binarytree node 1 depth 1 binarytree small_tree depth 2 binarytree medium_tree depth 4 noqa up007 returns true if the tree is full binarytree node 1 is_full true binarytree small_tree is_full true binarytree medium_tree is_full false
from __future__ import annotations

from collections.abc import Iterator
from dataclasses import dataclass


@dataclass
class Node:
    data: int
    left: Node | None = None
    right: Node | None = None

    def __iter__(self) -> Iterator[int]:
        if self.left:
            yield from self.left
        yield self.data
        if self.right:
            yield from self.right

    def __len__(self) -> int:
        return sum(1 for _ in self)

    def is_full(self) -> bool:
        if not self or (not self.left and not self.right):
            return True
        if self.left and self.right:
            return self.left.is_full() and self.right.is_full()
        return False


@dataclass
class BinaryTree:
    root: Node

    def __iter__(self) -> Iterator[int]:
        return iter(self.root)

    def __len__(self) -> int:
        return len(self.root)

    @classmethod
    def small_tree(cls) -> BinaryTree:
        
        binary_tree = BinaryTree(Node(2))
        binary_tree.root.left = Node(1)
        binary_tree.root.right = Node(3)
        return binary_tree

    @classmethod
    def medium_tree(cls) -> BinaryTree:
        
        binary_tree = BinaryTree(Node(4))
        binary_tree.root.left = two = Node(2)
        two.left = Node(1)
        two.right = Node(3)
        binary_tree.root.right = five = Node(5)
        five.right = six = Node(6)
        six.right = Node(7)
        return binary_tree

    def depth(self) -> int:
        
        return self._depth(self.root)

    def _depth(self, node: Node | None) -> int:  
        if not node:
            return 0
        return 1 + max(self._depth(node.left), self._depth(node.right))

    def is_full(self) -> bool:
        
        return self.root.is_full()


if __name__ == "__main__":
    import doctest

    doctest.testmod()