I am writing a library for working with special types of trees, called Foo trees. A Foo tree has very special structure. There some operations, called bar and baz, which only make sense on Foo trees. So I'm designing a FooTree class to represent Foo trees.
To construct a FooTree instance, one might pass some object representing a tree. This object will be checked for special structure and stored internally:
class FooTree(object):
def __init__(self, tree):
... # check that tree is a valid Foo tree
self._tree = tree
def bar(self):
# operation that only makes sense on a foo tree
The problem is: what if I construct a FooTree from a mutable object? For example, say Tree is a type whose instances are mutable:
tree = Tree()
... # build a valid Foo tree
foo_tree = FooTree(tree)
tree.remove_node(0) # tree is no longer a Foo tree
Since tree is no longer a valid Foo tree, and foo_tree wraps a reference to tree, foo_tree is no longer valid.
Instead I might copy the tree when creating a FooTree:
class FooTree(object):
def __init__(self, tree):
... # check that tree is a valid Foo tree
self._tree = tree.copy()
def bar(self):
# operation that only makes sense on a foo tree
This solves the problem, but creates a new one: Foo trees are typically very large, so copying them is expensive.
What patterns exist for creating FooTree objects from Tree objects, without copying and without the mutability problem?
For example, I might have FooTree accept a callable which produces a Tree:
class FooTreeBuilder(object):
def __init__(self, data):
self.data = data
def __call__(self):
tree = Tree()
... # build tree from self.data
return tree
class FooTree(object):
def __init__(self, builder):
self._tree = builder()
builder = FooTreeBuilder(data)
foo_tree = FooTree(builder)
Are there any better approaches? I'm specifically looking for approaches that lend well to Python implementations.
FooTreeBuilderexample I've given. What I'm looking for are suggestions for similar patterns, or arguments for why the former case (allowing the reference to be mutated) is OK.