TL;DR summary
How can I write foo = MyClass()
and have the MyClass
object know that its name is foo
?
Full Question
I want to write a library in Python that allows constructing a tree of objects, which support recursive traversal and naming. I would like to make this easy to use by automating the discovery of an object's name and parent object at the time it is created and added to the parent object. In this simple example, the name and parent object have to be explicitly passed into each object constructor:
class TreeNode:
def __init__(self, name, parent):
self.name = name
self.children = []
self.parent = parent
if parent is None:
self.fullname = name
else:
parent.register_child(self)
def register_child(self, child):
self.children.append(child)
child.fullname = self.fullname + "." + child.name
def recursive_print(self):
print(self.fullname)
for child in self.children:
child.recursive_print()
class CustomNode(TreeNode):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.foo = TreeNode(name="foo", parent=self)
self.bar = TreeNode(name="bar", parent=self)
root = TreeNode(name="root", parent=None)
root.a = CustomNode(name="a", parent=root)
root.recursive_print()
output:
root
root.a
root.a.foo
root.a.bar
What I would like to be able to do is omit the explicit name
and parent
arguments, something like:
class CustomNode(TreeNode):
def __init__(self):
self.foo = TreeNode()
self.bar = TreeNode()
root = TreeNode(parent=None)
root.a = CustomNode()
I have a partial solution at the moment where I have TreeNode.__setattr__()
check to see if it is assigning a new TreeNode
and if so name it and register it; but one shortcoming is that TreeNode.__init__()
cannot know its name
or parent
until after it returns, which would be preferable.
I am wondering if there is some neat way to do what I want, using metclasses or some other feature of the language.