Containment Tests

Suppose I’m interested in finding all sentences with a definite determiner in a subject. This means checking whether a particular subtree (corresponding to the subject) contains a particular element.

Let’s figure out how to compute whether a tree contains a particular piece of data, and then we’ll get back to figuring out how to grab the relevant subtree.

Containment tests for a class are often implemented in the __contains__ magic method, which defines the behavior of in. What should this method do for a tree? It should take a piece of data and tell us whether that data occurs at any node. This is the tree analogue of asking whether a list contains an element.

For a list, containment could be naturally implemented using a for-loop. So suppose we’re redefining the list class, __contains__ could be implemented something like this:

def __contains__[T](self: list[T], data: T) -> bool:
    for d in self:
        if d == data:
            return True
    
    return False

The implementation for Tree will follow the same basic idea, but a tree is not a single sequence. We’ll compare two ways of visiting its nodes:

In both kinds of search, we start at the top of the tree and work our way down, the question is which nodes we look at.