0

I have a problem where I want to change the class of some child elements in a class recursively.

I have a working solution, which is the following:

class PerformanceAggregator:
    def __init__(self, collection: pf.GenericPortfolioCollection):
        self.collection = collection
        self.change_children()

    def __getattr__(self, item):
        return getattr(self.collection, item, None)

    def change_children(self):
        for i in range(len(self.children)):
            if isinstance(self.children[i], pf.GenericPortfolioCollection):
                self.children[i] = PerformanceAggregator(self.children[i])

However, the change_children method is not very pythonic. It would be better with

class PerformanceAggregator2:
    def __init__(self, collection: pf.GenericPortfolioCollection):
        self.collection = collection
        self.change_children()

    def __getattr__(self, item):
        return getattr(self.collection, item, None)

    def change_children(self):
        for child in self.children:
            if isinstance(child, pf.GenericPortfolioCollection):
                child = PerformanceAggregator(child)

But this method does not work as intended. It does not replace the "child" element as the first method does. Do anybody have an idea about what is wrong?

4
  • In your second example, child is a variable that assigned to one of self.children. When you reassign it using child = PerformanceAggregator(child), you are not changing the reference in self.children at all. You are just assigning the variable child to the new instance, but nothing else happens with it since you never update the parent object. Commented Dec 12, 2019 at 11:03
  • 1
    Does this answer your question? Assigning values to variables in a list using a loop Commented Dec 12, 2019 at 11:04
  • Answer is in the duplicate. Mandatory reading for you: this article explains in great length and depth all you need to know about python "variables". Commented Dec 12, 2019 at 11:08
  • And for the pythonic way to deal with this case: use enumerate() so you get both the child and it's index. Commented Dec 12, 2019 at 11:09

1 Answer 1

1

When you're looping through self.children, you're assigning child to PerformanceAggregator(child) but not necessarily updating the child element in self.children.

This should work:

     def change_children(self):
         for (val,child) in enumerate(self.children):
             if isinstance(child, pf.GenericPortfolioCollection):
                 self.children[val] = PerformanceAggregator(child)
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.