pythonpython-3.xclassobject-composition

What is the correct way to access a class composite inside one of its components, if that's even advisable?


Suppose I have these two classes:

class Branch():
    def __init__(self, id, leaves):
        self.id = id
        self.leaves = leaves
    
class Leaf():
    def __init__(self, color)
        self.color = color
    
    def describe()
        print("This leaf is " + color)

Every Leaf belongs to a Branch. A Branch continues to exist whether it has any leaves or not, but a Leaf cannot meaningfully exist without a Branch (real-life logic aside). That means I can easily get every Leaf from a Branch through the Branch.leaves attribute. If I understood composition correctly, a Branch is the composite and every Leaf in Branch.leaves is one of its components?

However, no Leaf actually knows to which Branch it belongs to. So, I can't have it print "This leaf is orange and belongs to branch #14". I could just add a Leaf.branch attribute and pass it whenever I initialize a new Leaf instance, seeing how a Branch must already exist for that to happen, but that seems very wrong to me, because then it looks like the Branch belongs to the Leaf.

The question is: what is the most pythonic and correct way to do what I described I can't do in my example? Is what I thought felt very wrong not actually bad at all? Or rather, did this problem arise from bad design and I should look at this from another angle? Thanks in advance.


Solution

  • In a complex tree of views and subviews, every individual view has a pointer to the superview and to the window. In a complex tree of menu items and submenus, every item has a pointer to the top menu. It's really common for a child to know its parent or for an item to know its container. Some designs wouldn't be possible without that.

    In languages where you have to worry about memory management, the reference to the parent must be a weak reference, which means that the child has never to worry about the live cycle of its parent (while the contrary is not true). Even in Python, the parent owns the child which it is free to create or delete when required but, obviously, the child can never create or delete its parent (which it could not do anyway since it doesn't know its own container or owner).

    So, there is a clear hierarchical relationship between the two objects, but that has nothing to do with the fact that they can or cannot know each other.