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.
FooTreeBuilder
example 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.