Exercise 2: A MaxDepth Visitor With Zero Node-Class Changes — Possible Solution ==================================================================== THE NEW VISITOR ------------------------------ class MaxDepth: def visit_literal(self, node): return 1 def visit_grouping(self, node): return 1 + node.expression.accept(self) def visit_unary(self, node): return 1 + node.right.accept(self) def visit_binary(self, node): return 1 + max(node.left.accept(self), node.right.accept(self)) A Literal is a leaf, so its own depth is 1. Every other node type's depth is 1 (for itself) plus the deepest of whichever children it has — exactly the recursive definition of tree depth, expressed once per node type, with no isinstance check anywhere in the class. RESULTS ------------------------------ MaxDepth of '2 + 3 * 4': 3 Binary(+) depth 3 Literal(2.0) depth 1 Binary(*) depth 2 Literal(3.0) depth 1 Literal(4.0) depth 1 MaxDepth of '((1 + 2) * (3 + 4))': 5 Grouping depth 5 Binary(*) depth 4 Grouping depth 3 Binary(+) -> two Literals depth 2 / 1 Grouping depth 3 Binary(+) -> two Literals depth 2 / 1 WHY THIS WORKS AS AN ANSWER ------------------------------ This is the chapter's own central claim, made concrete a second time: Literal, Grouping, Unary, and Binary were not opened, edited, or even re-read to add this entirely new operation. MaxDepth is a genuinely new capability over the exact same four node types NodeCounter already used in the chapter — and, just like NodeCounter, it cost one new class with one method per existing node type, zero edits anywhere else. An isinstance-chain version of MaxDepth would have been a fourth hand-written four-way type check, on top of the three the chapter already counted (13 total isinstance(node, ...) checks across evaluate_isinstance, stringify_isinstance, and count_nodes_isinstance) — this exercise's MaxDepth would have pushed that real, growing total to 17, while the Visitor-based accept() dispatch count stays at 4, exactly where it's been since the first node class was written.